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

Ejemplo:

> db.stuff.save({"foo":"bar"}); > db.stuff.find({"foo":"bar"}).count(); 1 > db.stuff.find({"foo":"BAR"}).count(); 0 

    Puedes usar una expresión regular .

    En tu ejemplo, eso sería:

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

    Debo decir, sin embargo, que tal vez podrías minimizar (o boost) el valor en el camino en lugar de incurrir en el costo adicional cada vez que lo encuentres. Obviamente, esto no funcionará para los nombres de las personas y demás, pero tal vez casos de uso como tags.

    ACTUALIZAR:

    La respuesta original ahora está obsoleta. Mongodb ahora es compatible con la búsqueda avanzada de texto completo, con muchas características.

    RESPUESTA ORIGINAL:

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

    Incluso con pequeños conjuntos de datos, no es muy eficiente. Usted toma un golpe de CPU mucho más grande de lo que su consulta garantiza, lo que podría convertirse en un problema si está tratando de alcanzar la escala.

    Como alternativa, puede almacenar una copia en mayúsculas y buscar en contra de eso. Por ejemplo, tengo una tabla de Usuario que tiene un nombre de usuario que es una combinación de mayúsculas y minúsculas, pero el ID es una copia en mayúscula del nombre de usuario. Esto asegura que la duplicación sensible a mayúsculas y minúsculas es imposible (no se permitirán tanto “Foo” como “foo”), y puedo buscar por id = username.toUpperCase () para obtener una búsqueda de usuario insensible a mayúsculas y minúsculas.

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

    Tenga en cuenta que el ejemplo anterior:

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

    hará que cada entrada que contenga la barra coincida con la consulta (bar1, barxyz, barra libre), podría ser muy peligroso para una búsqueda de nombre de usuario en una función de autenticación …

    Es posible que deba hacer coincidir solo el término de búsqueda utilizando la syntax de expresiones regulares adecuada como:

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

    Vea http://www.regular-expressions.info/ para ayuda de syntax en expresiones regulares

    Si necesita crear la expresión regular de una variable, esta es una forma mucho mejor de hacerlo: https://stackoverflow.com/a/10728069/309514

    Entonces puede hacer algo como:

     var string = "SomeStringToFind"; var regex = new RegExp(["^", string, "$"].join(""), "i"); // Creates a regex of: /^SomeStringToFind$/i db.stuff.find( { foo: regex } ); 

    Esto tiene el beneficio de ser más programático o puede obtener un aumento de rendimiento comstackndo con anticipación si lo está reutilizando mucho.

    A partir de Mongodb 3.4 debe usar un índice de intercalación insensible a mayúsculas y minúsculas. Esta es la forma más rápida de hacer una búsqueda insensible a mayúsculas y minúsculas en conjuntos de datos de tamaño cada vez mayor. Personalmente, envié un correo electrónico a uno de los fundadores para que funcione y lo hizo posible. (Fue un problema en JIRA durante 5 años, y muchos han solicitado la función). Así es como funciona:

    Se realiza un índice que no distingue entre mayúsculas y minúsculas al especificar una intercalación con una intensidad de 1 o 2. Puede crear un índice insensible a mayúsculas y minúsculas como este:

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

    O puede hacerlo para toda la colección de forma predeterminada cuando crea la base de datos de la siguiente manera:

     db.createCollection("Cities",{collation: {locale: "en",strength:2}}); 

    Y úsalo así:

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

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

    De forma alternativa, puede hacer que todos los índices usen una intercalación de manera predeterminada cuando realice la recostackción de esta manera:

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

    El beneficio de este método es una eficiencia y velocidad mucho mejores en conjuntos de datos más grandes.

    Para más información: https://jira.mongodb.org/browse/SERVER-90 , https://docs.mongodb.com/manual/reference/collation/

     db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity 

    TL; DR

    Forma correcta de hacer esto en mongo

    No use RegExp

    Ir natural Y usar la indexación incorporada de mongodb, búsqueda

    Paso 1 :

     db.articles.insert( [ { _id: 1, subject: "coffee", author: "xyz", views: 50 }, { _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 }, { _id: 3, subject: "Baking a cake", author: "abc", views: 90 }, { _id: 4, subject: "baking", author: "xyz", views: 100 }, { _id: 5, subject: "Café Con Leche", author: "abc", views: 200 }, { _id: 6, subject: "Сырники", author: "jkl", views: 80 }, { _id: 7, subject: "coffee and cream", author: "efg", views: 10 }, { _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 } ] ) 

    Paso 2 :

    Necesita crear índice en cualquier campo TEXTO que quiera buscar, sin que la consulta de indexación sea extremadamente lenta

     db.articles.createIndex( { subject: "text" } ) 

    paso 3 :

     db.articles.find( { $text: { $search: "coffee",$caseSensitive :true } } ) //FOR SENSITIVITY db.articles.find( { $text: { $search: "coffee",$caseSensitive :false } } ) //FOR INSENSITIVITY 

    Mongo (versión actual 2.0.0) no permite búsquedas insensibles a mayúsculas y minúsculas frente a campos indexados; consulte su documentación . Para los campos no indexados, las expresiones regulares enumeradas en las otras respuestas deberían estar bien.

    Usar Mongoose esto funcionó para mí:

     var find = function(username, next){ User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){ if(err) throw err; next(null, res); }); } 

    El mejor método es en el idioma de su elección, al crear un contenedor de modelo para sus objetos, haga que su método save () recorra un conjunto de campos que usted buscará y que también estarán indexados; ese conjunto de campos debe tener contrapartes en minúsculas que luego se usan para buscar.

    Cada vez que el objeto se guarda de nuevo, las propiedades en minúsculas se verifican y actualizan con cualquier cambio en las propiedades principales. Esto lo hará para que pueda buscar de manera eficiente, pero oculte el trabajo adicional necesario para actualizar los campos lc cada vez.

    Los campos en minúscula podrían ser una clave: almacén de objetos de valor o solo el nombre del campo con un lc_ con prefijo. Utilizo el segundo para simplificar las consultas (la consulta profunda de objetos puede ser confusa a veces).

    Nota: desea indexar los campos lc_, no los campos principales de los que se basan.

    Supongamos que desea buscar “columna” en “Tabla” y desea buscar caso insensible. La mejor y más eficiente es la siguiente;

     //create empty JSON Object mycolumn = {}; //check if column has valid value if(column) { mycolumn.column = {$regex: new RegExp(column), $options: "i"}; } Table.find(mycolumn); 

    El código anterior simplemente agrega su valor de búsqueda como RegEx y busca con los criterios insensibles establecidos con la opción “i”.

    Todo lo mejor.

    Una cosa muy importante a tener en cuenta cuando se utiliza una consulta basada en Regex: cuando hace esto para un sistema de inicio de sesión, escapa cada carácter que está buscando, y no olvide los operadores ^ y $. Lodash tiene una buena función para esto , si ya la está usando:

     db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'}) 

    ¿Por qué? Imagine que un usuario ingresa .* Como su nombre de usuario. Eso coincidiría con todos los nombres de usuario, permitiendo un inicio de sesión adivinando la contraseña de cualquier usuario.

    El marco de agregación se introdujo en mongodb 2.2. Puede usar el operador de cadena “$ strcasecmp” para hacer una comparación entre cadenas que no distinga entre mayúsculas y minúsculas. Es más recomendado y más fácil que usar regex.

    Aquí está el documento oficial en el operador del comando de agregación: https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp .

    Usar un filtro funciona para mí en C #.

     string s = "searchTerm"; var filter = Builders.Filter.Where(p => p.Title.ToLower().Contains(s.ToLower())); var listSorted = collection.Find(filter).ToList(); var list = collection.Find(filter).ToList(); 

    Incluso puede usar el índice porque creo que se llaman los métodos después de que se produce el retorno, pero aún no lo he probado.

    Esto también evita un problema de

     var filter = Builders.Filter.Eq(p => p.Title.ToLower(), s.ToLower()); 

    que mongodb pensará p.Title.ToLower () es una propiedad y no se correlacionará correctamente.

    Puede usar Índices insensibles a mayúsculas y minúsculas :

    El siguiente ejemplo crea una colección sin intercalación predeterminada, luego agrega un índice en el campo de nombre con una intercalación insensible a mayúsculas y minúsculas. Componentes internacionales para Unicode

     /* strength: CollationStrength.Secondary * Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of * base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary * differences. */ db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } ) 

    Para usar el índice, las consultas deben especificar la misma intercalación.

     db.users.insert( [ { name: "Oğuz" }, { name: "oğuz" }, { name: "OĞUZ" } ] ) // does not use index, finds one result db.users.find( { name: "oğuz" } ) // uses the index, finds three results db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } ) // does not use the index, finds three results (different strength) db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } ) 

    o puede crear una colección con colación predeterminada:

     db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } ) db.users.createIndex( { name : 1 } ) // inherits the default collation 

    Para buscar una variable y escapar de ella:

     const escapeStringRegexp = require('escape-string-regexp') const name = 'foo' db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', 'i')}) 

    El escape de la variable protege la consulta contra ataques con ‘. *’ U otra expresión regular.

    escape-string-regexp

     db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}}); 

    Creé un Func simple para la expresión regular insensible a mayúsculas / minúsculas, que uso en mi filtro.

     private Func CaseInsensitiveCompare = (field) => BsonRegularExpression.Create(new Regex(field, RegexOptions.IgnoreCase)); 

    Luego simplemente filtra en un campo de la siguiente manera.

     db.stuff.find({"foo": CaseInsensitiveCompare("bar")}).count(); 

    Como puede ver en mongo docs, desde la versión 3.2, $text index no distingue entre mayúsculas y minúsculas por defecto: https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitivity

    Cree un índice de texto y use $ text operator en su consulta .

    Estos han sido probados para búsquedas de cadenas

     {'_id': /.*CM.*/} ||find _id where _id contains ->CM {'_id': /^CM/} ||find _id where _id starts ->CM {'_id': /CM$/} ||find _id where _id ends ->CM {'_id': /.*UcM075237.*/i} ||find _id where _id contains ->UcM075237, ignore upper/lower case {'_id': /^UcM075237/i} ||find _id where _id starts ->UcM075237, ignore upper/lower case {'_id': /UcM075237$/i} ||find _id where _id ends ->UcM075237, ignore upper/lower case 

    Me enfrenté a un problema similar y esto es lo que funcionó para mí:

      const flavorExists = await Flavors.findOne({ 'flavor.name': { $regex: flavorName, $options: 'i' }, }); 

    Use RegExp , en caso de que otras opciones no le sirvan, RegExp es una buena opción. Hace la cadena sensible a mayúsculas y minúsculas.

     var username = "John"; var uname = new RegExp(username, "i"); 

    El valor de uname será como /John/i .

    use uname en consultas en lugar de nombre de usuario, y luego está hecho.

    Espero que funcione también para ti. Todo lo mejor.