Сортировка без учета регистра в MongoDB

Как я могу отсортировать коллекцию MongoDB по заданному полю без учета регистра? По умолчанию я получаю AZ перед AZ.


person Varun Kumar    schedule 08.04.2014    source источник


Ответы (10)


Обновление: На данный момент mongodb имеет индексы без учета регистра:

Users.find({})
  .collation({locale: "en" })
  .sort({name: 1})
  .exec()
  .then(...)

оболочка:

db.getCollection('users')
  .find({})
  .collation({'locale':'en'})
  .sort({'firstName':1})

Обновление: этот ответ устарел, 3.4 будет иметь индексы без учета регистра. Обратитесь к JIRA за дополнительной информацией https://jira.mongodb.org/browse/SERVER-90< /а>


К сожалению, в MongoDB пока нет индексов, нечувствительных к регистру: https://jira.mongodb.org/browse/SERVER-90 и задача была отложена.

Это означает, что единственный способ сортировки без учета регистра в настоящее время - это фактически создать конкретное поле «в нижнем регистре», скопировав значение (конечно, в нижнем регистре) рассматриваемого поля сортировки и отсортировав его вместо этого.

person Sammaye    schedule 08.04.2014
comment
Таким образом, нет возможности сортировать результаты с нечувствительными, если только не создается новое поле только с нижними или верхними значениями. райт?? - person Varun Kumar; 08.04.2014
comment
@VarunKumar да, это один из плохих моментов MongoDB, лично я бы не стал использовать приведенный ниже ответ, MongoDB будет ограничен 32 мегабайтами сортировки без индекса, что приведет к разрешению очень маленьких наборов результатов. - person Sammaye; 08.04.2014
comment
@VarunKumar, если быть более точным, вы будете ограничены сортировкой от 2 до 32 000 записей в зависимости от размера документов, не только это, но и сортировка будет полностью в памяти, что будет убийцей - person Sammaye; 08.04.2014
comment
Святое ***, наконец-то! - person Sammaye; 16.09.2016
comment
@SSHThis, не могли бы вы поделиться ссылкой, где это разрешено? - person Rahul Matte; 27.09.2016
comment
@RahulMatte щелкните ссылку JIRA, она разрешена в последней нестабильной версии, как и сопоставления. - person Sammaye; 27.09.2016
comment
Как сказано в ссылке JIRA, индекс без учета регистра выйдет с MongoDB v. 3.3.11, который в основном вам нужно обновить mongodb для этой функции. вы можете найти новую версию здесь, но на сегодняшний день это 3.2.10, новая версия может быть выпущена в будущем - mongodb.com/download-center#community - person Teerakiat Chitawattanarat; 23.10.2016
comment
Это решается MongoDB. Взгляните на мой ответ ниже - person Mladen Janjetovic; 28.02.2017
comment
@Sammaye, есть ли способ использовать case insensitive index с драйвером reactive-mongo? Я использую scala с mongo. - person oblivion; 31.07.2017
comment
@oblivion, к сожалению, я не программирую на Scala - person Sammaye; 31.07.2017
comment
Сопоставления поддерживаются агрегатом, поэтому я бы сказал «да». - person Sammaye; 14.12.2017
comment
@Ф.Х. вы используете сопоставления? - person Sammaye; 15.07.2019
comment
@Ф.Х. чтобы было ясно, почему сортировка чувствительна к регистру без сортировки ios, потому что она использует лексическую сортировку без сортировки - person Sammaye; 15.07.2019
comment
обновить извините, был передан неправильный объект сопоставления - подтверждено, что он работает с агрегацией - person F.H.; 15.07.2019
comment
Хороший ответ. Я просто хочу добавить немного документации: docs.mongodb.com/manual/reference/collation - person code đờ; 22.06.2021

Сортировка работает так же в MongoDB, но вы можете сделать это на лету с помощью агрегата:

Возьмите следующие данные:

{ "field" : "BBB" }
{ "field" : "aaa" }
{ "field" : "AAA" }

Итак, со следующим утверждением:

db.collection.aggregate([
    { "$project": {
       "field": 1,
       "insensitive": { "$toLower": "$field" }
    }},
    { "$sort": { "insensitive": 1 } }
])

Будет давать такие результаты, как:

{
    "field" : "aaa",
    "insensitive" : "aaa"
},
{
    "field" : "AAA",
    "insensitive" : "aaa"
},
{
    "field" : "BBB",
    "insensitive" : "bbb"
}

Фактический порядок вставки будет сохранен для любых значений, приводящих к тому же ключу при преобразовании.

person Neil Lunn    schedule 08.04.2014
comment
Да .. это выглядит хорошо .. но я хочу реализовать то же самое из java-кода .. Так что будет полезнее, если вы поделитесь со мной тем, как этого можно достичь из класса Java с обработкой mongodb и объекта запроса. - person Varun Kumar; 08.04.2014
comment
@VarunKumar В основном вам нужно создавать записи DBObject, которые вы передаете в агрегатный метод. В документации есть этот пример Ресурсы. Так что сложностей с переводом быть не должно. И учитывая, что это реальный ответ, чтобы показать, как это можно сделать, это не должно быть слишком сложно. - person Neil Lunn; 08.04.2014
comment
Будет ли это медленным (т.е. оценивается ли агрегат каждый раз?) - person Archimedes Trajano; 19.03.2016
comment
Кто-нибудь решил проблему с помощью spring-data-mongo или Java? - person freak007; 02.01.2018

Это была проблема довольно долгое время в MongoDB JIRA, но теперь она решена. . Подробную документацию см. в этих примечаниях к выпуску. Вы должны использовать collation.

User.find()
    .collation({locale: "en" }) //or whatever collation you want
    .sort({name:1})
    .exec(function(err, users) {
        // use your case insensitive sorted results
    });
person Mladen Janjetovic    schedule 28.02.2017

Добавление кода .collation({'locale':'en'}) помогло решить мою проблему.

person Monu Chaudhary    schedule 24.03.2019
comment
Но когда я использую сопоставление в Mongoose с агрегацией, я получаю ошибку MongooseError: Callback должен быть функцией, полученной [object Object] - person Monu Chaudhary; 02.04.2019

На данный момент (mongodb 4) вы можете сделать следующее:

оболочка монго:

db.getCollection('users')
  .find({})
  .collation({'locale':'en'})
  .sort({'firstName':1});

мангуста:

Users.find({})
  .collation({locale: "en" })
  .sort({name: 1})
  .exec()
  .then(...)

Вот поддерживаемые языки и локали монгодб.

person Wajahath    schedule 16.01.2019

В мангусте: -

Customer.find()
  .collation({locale: "en" })
  .sort({comapany: 1})
person G Bojegowda    schedule 16.12.2019

Вот это на Яве. Я смешал без аргументов и первые варианты key-val BasicDBObject просто для разнообразия

        DBCollection coll = db.getCollection("foo");

        List<DBObject> pipe = new ArrayList<DBObject>();

        DBObject prjflds = new BasicDBObject();
        prjflds.put("field", 1);
        prjflds.put("insensitive", new BasicDBObject("$toLower", "$field"));

        DBObject project = new BasicDBObject();
        project.put("$project", prjflds);
        pipe.add(project);

        DBObject sort = new BasicDBObject();
        sort.put("$sort", new BasicDBObject("insensitive", 1));
        pipe.add(sort);

        AggregationOutput agg = coll.aggregate(pipe);

        for (DBObject result : agg.results()) {
            System.out.println(result);
        }
person Buzz Moschetti    schedule 14.06.2015

Если вы хотите отсортировать и вернуть все данные в документе, вы можете добавить document: "$$ROOT"

db.collection.aggregate([
  { 
    $project: {
      field: 1,
      insensitive: { $toLower: "$field" },
      document: "$$ROOT"
    }
  },
  { $sort: { insensitive: 1 } }
]).toArray()
person Renato Augusto    schedule 11.02.2021

Пробовал все вышеперечисленное и отвечает Закрепление результата

Ответ-1:

db.collection.aggregate([
    { "$project": {
       "field": 1,
       "insensitive": { "$toLower": "$field" }
    }},
    { "$sort": { "insensitive": 1 } } ])

Совокупный запрос преобразует поле в меньшее, поэтому производительность для больших данных низкая.

Ответ-2:

db.collection.find({}).collation({locale: "en"}).sort({"name":1})

По умолчанию mongo следует правилам кодирования uft-8 (Z имеет более высокий приоритет, чем a), поэтому переопределяет правила, специфичные для языка. Его быстрое сравнение с приведенным выше запросом. Посмотрите официальный документ, чтобы настроить правила.

https://docs.mongodb.com/manual/reference/collation/

person SANJEEV RAVI    schedule 09.03.2020

Мы решаем эту проблему с помощью функции .sort в массиве JavaScript.

Вот код


    function foo() {
      let results = collections.find({
        _id: _id
      }, {
        fields: {
          'username': 1,
        }
      }).fetch();

      results.sort((a, b)=>{
        var nameA = a.username.toUpperCase();
        var nameB = b.username.toUpperCase();

        if (nameA  nameB) {
          return 1;
        }
        return 0;
      });

      return results;
    }

person Kevin Alviola    schedule 07.04.2017
comment
Сортировка в вашем приложении — плохая идея - person arg20; 27.09.2018