Clasificación insensible a mayúsculas y minúsculas en MongoDB

4 minutos de lectura

avatar de usuario
varun kumar

¿Cómo puedo ordenar una colección de MongoDB por un campo determinado, sin distinción entre mayúsculas y minúsculas? De forma predeterminada, obtengo AZ antes de az.

avatar de usuario
sammaye

Actualizar:
A partir de ahora, mongodb tiene índices que no distinguen entre mayúsculas y minúsculas:

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

caparazón:

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

Actualizar: Esta respuesta está desactualizada, 3.4 tendrá índices que no distinguen entre mayúsculas y minúsculas. Consulte el JIRA para obtener más información. https://jira.mongodb.org/browse/SERVER-90


Desafortunadamente, MongoDB aún no tiene índices que no distingan entre mayúsculas y minúsculas: https://jira.mongodb.org/browse/SERVER-90 y la tarea se ha retrasado.

Esto significa que la única forma de ordenar que no distingue entre mayúsculas y minúsculas actualmente es crear un campo específico “en minúsculas”, copiando el valor (en minúsculas, por supuesto) del campo de ordenación en cuestión y ordenándolo en su lugar.

  • Por lo tanto, no hay opción para ordenar los resultados con insensibles a menos que se cree un nuevo campo solo con valores en mayúsculas o minúsculas. ryt??

    – Varun Kumar

    08/04/2014 a las 11:07

  • @VarunKumar sí, es uno de los puntos negativos de MongoDB, personalmente no usaría la respuesta a continuación, MongoDB se limitará a 32 megas sin que el índice dé como resultado conjuntos de resultados muy pequeños.

    – Sammaye

    08/04/2014 a las 11:16


  • @VarunKumar, para ser más precisos, estará limitado a clasificar entre 2 y 32 000 registros según el tamaño de los documentos, no solo eso, sino que la clasificación estará completamente en la memoria, lo que será un asesino

    – Sammaye

    08/04/2014 a las 11:17


  • @FH ¿estás usando intercalaciones?

    – Sammaye

    15 de julio de 2019 a las 13:39

  • @FH para aclarar la razón por la que sort distingue entre mayúsculas y minúsculas sin intercalaciones ios porque utiliza clasificación léxica sin intercalaciones

    – Sammaye

    15 de julio de 2019 a las 13:40

La clasificación funciona así en MongoDB, pero puede hacerlo sobre la marcha con agregado:

Toma los siguientes datos:

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

Entonces con la siguiente declaración:

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

Produciría resultados como:

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

El orden real de inserción se mantendría para cualquier valor que dé como resultado la misma clave cuando se convierta.

  • Sí… esto se ve bien… pero quiero implementar lo mismo desde un código Java… Así que será más útil si me compartes cómo se puede lograr esto desde la clase Java con el manejo de mongodb y el objeto de consulta.

    – Varun Kumar

    08/04/2014 a las 11:10

  • @VarunKumar Básicamente, necesita construir entradas DBObject que pase al método agregado. Hay este ejemplo en los recursos de documentación. Así que no debería ser difícil de traducir. Y teniendo en cuenta que es una respuesta real para mostrar cómo se puede hacer, eso no debería ser demasiado difícil.

    – Neil Lunn

    08/04/2014 a las 11:30

  • ¿Sería esto lento (es decir, se evalúa el agregado cada vez?)

    – Arquímedes Trajano

    19 de marzo de 2016 a las 0:13

  • ¿Alguien resolvió el problema usando spring-data-mongo o Java?

    – freak007

    2 de enero de 2018 a las 19:07

avatar de usuario
Mladen Janjetovic

esto ha sido un tema durante bastante tiempo en MongoDB JIRA, pero ahora está resuelto. Echa un vistazo a estas notas de la versión para obtener documentación detallada. Deberías usar collation.

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

avatar de usuario
monu chaudhary

Agregando el código .collation({'locale':'en'}) ayudó a resolver mi problema.

A partir de ahora (mongodb 4), puede hacer lo siguiente:

caparazón mongo:

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

mangosta:

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

Aquí están Idiomas y configuraciones regionales admitidos por mongodb.

avatar de usuario
G Boje Gowda

En Mangosta:-

Customer.find()
  .collation({locale: "en" })
  .sort({comapany: 1})

avatar de usuario
JohnnyHK

Aquí está en Java. Mezclé variantes sin argumentos y de primera clave-val de BasicDBObject solo por variedad

        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);
        }

¿Ha sido útil esta solución?