sort pattern insensitive index fulltext mongodb case-insensitive

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



mongoose case insensitive (22)

Ejemplo:

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


A partir de Mongodb 3.4 debe utilizar un índice de intercalación que no distinga mayúsculas y minúsculas. Esta es la forma más rápida de realizar una búsqueda sin distinción de mayúsculas y minúsculas en conjuntos de datos de tamaño cada vez mayor. Personalmente, le envié un correo electrónico a uno de los fundadores para que funcionara, ¡y lo hizo realidad! (Fue un problema en JIRA durante aproximadamente 5 años, 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 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 cree la base de datos de esta 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.

Como alternativa, puede hacer que todos los índices utilicen una intercalación de forma predeterminada cuando realice la recopilación de esta forma:

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

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

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


Algo que es muy importante tener en cuenta al utilizar una consulta basada en Regex: cuando haga esto para un sistema de inicio de sesión, evite todos los caracteres que está buscando y no olvide los operadores ^ y $. Lodash tiene una buena función para esto , si ya lo está utilizando:

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

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




El mejor método está en el idioma de su elección. Cuando cree un contenedor de modelo para sus objetos, haga que su método save () se repita en un conjunto de campos en los que buscará y que también están indexados. esos conjuntos de campos deben tener contrapartes en minúsculas que luego se utilizan para la búsqueda.

Cada vez que el objeto se guarda de nuevo, las propiedades en minúsculas se revisan 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 de lc cada vez.

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

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


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


He creado un Func simple para la expresión regular que no distingue entre mayúsculas y minúsculas, que uso en mi filtro.

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

Entonces simplemente filtra en un campo de la siguiente manera.

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


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

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


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


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

Escapar de la variable protege la consulta contra ataques con ''. *'' U otra expresión regular.

escape-string-regexp


Podrías usar una regex .

En tu ejemplo sería:

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

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


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 que no distingue entre 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 utilizar 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 intercalación predeterminada:

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


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

Entonces puedes 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 la ventaja de ser más programático o puede obtener un aumento de rendimiento si lo compila con anticipación si lo reutiliza mucho.


Supongamos que desea buscar la "columna" en la "Tabla" y desea una búsqueda insensible al caso. La forma mejor y 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 solo agrega su valor de búsqueda como RegEx y busca con criterios de insensibilidad establecidos con "i" como opción.

Todo lo mejor.


TL; DR

Manera correcta de hacer esto en mongo.

No utilice RegExp

Vaya natural y use la indexación incorporada de mongodb, busque

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 :

La necesidad de crear un índice en cualquier campo de TEXTO que desee buscar, sin indizar la consulta será 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


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, openbar), 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 que coincida solo con el término de búsqueda utilizando la sintaxis de expresiones regulares apropiada como:

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

Consulte http://www.regular-expressions.info/ para obtener ayuda sobre la sintaxis de las expresiones regulares


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


Usar un filtro me funciona en C #.

string s = "searchTerm"; var filter = Builders<Model>.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 los métodos se llaman después de que se produce la devolución, pero aún no lo he probado.

Esto también evita un problema de

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

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


Use RegExp , en caso de que alguna otra opción no le funcione, RegExp es una buena opción. Hace que la cadena sea sensible al caso.

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

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

use uname en las consultas en lugar del nombre de usuario, y luego se hace.

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


ACTUALIZAR:

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

RESPUESTA ORIGINAL:

Se debe tener en cuenta que la búsqueda con regex insensible a mayúsculas / i significa que mongodb no puede buscar por índice, por lo que las consultas contra grandes conjuntos de datos pueden llevar mucho tiempo.

Incluso con conjuntos de datos pequeños, no es muy eficiente. Usted recibe un mayor impacto de la CPU que lo que garantiza su consulta, lo que podría convertirse en un problema si está intentando alcanzar una escala.

Como alternativa, puede almacenar una copia en mayúsculas y buscar contra eso. Por ejemplo, tengo una tabla de usuario que tiene un nombre de usuario que es un caso mixto, pero la identificación es una copia en mayúsculas del nombre de usuario. Esto garantiza que la duplicación que distingue entre 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 que no distinga mayúsculas y minúsculas de un nombre de usuario.

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.


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


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