Saltar al contenido

MongoDB: ¿Es posible realizar una consulta que no distinga entre mayúsculas y minúsculas?

Solución:

Podrías usar una expresión regular.

En su ejemplo, eso sería:

db.stuff.find( { foo: /^bar$/i } );

Sin embargo, debo decir que tal vez pueda reducir (o aumentar) el valor en el camino en lugar de incurrir en un costo adicional cada vez que lo encuentre. Obviamente, esto no funcionará para nombres de personas y demás, pero tal vez casos de uso como etiquetas.

ACTUALIZAR:

La respuesta original ahora está obsoleta. Mongodb ahora admite la búsqueda avanzada de texto completo, con muchas funciones.

RESPUESTA ORIGINAL:

Cabe señalar que la búsqueda con expresiones regulares / i que no distingue entre mayúsculas y minúsculas significa que mongodb no puede buscar por índice, por lo que las consultas en conjuntos de datos grandes pueden llevar mucho tiempo.

Incluso con pequeños conjuntos de datos, no es muy eficiente. Obtienes un impacto de CPU mucho mayor de lo que justifica tu consulta, lo que podría convertirse en un problema si estás tratando de escalar.

Como alternativa, puede almacenar una copia en mayúsculas y buscar en ella. Por ejemplo, tengo una tabla de usuarios que tiene un nombre de usuario que es una combinación de mayúsculas y minúsculas, pero la identificación es una copia en mayúsculas del nombre de usuario. Esto asegura que la duplicación sensible a mayúsculas y minúsculas es imposible (no se permitirá tener “Foo” y “foo”), y puedo buscar por id = username.toUpperCase () para obtener una búsqueda de nombre de usuario que no distinga entre mayúsculas y minúsculas.

Si su campo es grande, como el cuerpo de un mensaje, la duplicación de datos probablemente no sea una buena opción. Creo que usar un indexador extraño como Apache Lucene es la mejor opción en ese caso.

A partir de MongoDB 3.4, la forma recomendada de realizar búsquedas rápidas que no distinguen entre mayúsculas y minúsculas es utilizar un Índice que no distingue entre mayúsculas y minúsculas.

Yo personalmente le envié un correo electrónico a uno de los fundadores para que esto funcione, ¡y él lo hizo posible! Fue un problema en JIRA desde 2009, y muchos han solicitado la función. Así es como funciona:

Un índice que no distingue entre mayúsculas y minúsculas se crea especificando una intercalación con una fuerza de 1 o 2. Puede crear un índice que no distinga entre mayúsculas y minúsculas como este:

db.cities.createIndex(
  { city: 1 },
  { 
    collation: {
      locale: 'en',
      strength: 2
    }
  }
);

También puede especificar una intercalación predeterminada por colección cuando las crea:

db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );

En cualquier caso, para utilizar el índice que no distingue entre mayúsculas y minúsculas, debe especificar la misma intercalación en el find operación que se utilizó al crear el índice o la colección:

db.cities.find(
  { city: 'new york' }
).collation(
  { locale: 'en', strength: 2 }
);

Esto devolverá “Nueva York”, “nueva york”, “Nueva york”, etc.

Otras notas

  • Las respuestas que sugieren usar la búsqueda de texto completo es incorrecta en este caso (y potencialmente peligroso). La pregunta era sobre cómo hacer una consulta que no distingue entre mayúsculas y minúsculas, p. Ej. username: 'bill' pareo BILL o Bill, no una consulta de búsqueda de texto completo, que también coincidiría con palabras derivadas de bill, tal como Bills, billed etc.

  • Las respuestas que sugieren usar expresiones regulares son lentas, porque incluso con índices, la documentación dice:

    “Las consultas de expresiones regulares que no distinguen entre mayúsculas y minúsculas generalmente no pueden utilizar índices de forma eficaz. La implementación de $ regex no reconoce la intercalación y no puede utilizar índices que no distinguen entre mayúsculas y minúsculas”.

    $regex las respuestas también corren el riesgo de una inyección de entrada del usuario.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *