Una nota para todos los que intentarán usar una respuesta que involucre expresiones regulares: las expresiones regulares deben desinfectarse.
sean
Respuestas:
126
La solución de Chris Fulstow funcionará (+1), sin embargo, puede que no sea eficiente, especialmente si su colección es muy grande. Las expresiones regulares no arraigadas (las que no comienzan con ^, que anclan la expresión regular al comienzo de la cadena) y las que usan la ibandera para no distinguir entre mayúsculas y minúsculas no usarán índices, incluso si existen.
Una opción alternativa que podría considerar es desnormalizar sus datos para almacenar una versión en minúscula del namecampo, por ejemplo como name_lower. Luego puede consultar eso de manera eficiente (especialmente si está indexado) para coincidencias exactas que no distinguen entre mayúsculas y minúsculas, como:
Excelente respuesta, mi enfoque de expresiones regulares realmente se ralentiza una vez que tiene que escanear algunos millones de documentos.
Chris Fulstow
34
En realidad, esto no es del todo correcto, porque puede encontrar "Andrew algo" mientras busca "Andrew". Así que ajusta la expresión regular a: new RegExp('^'+ username + '$', "i")para que sea una coincidencia exacta.
Tarion
9
Según el sitio web de MongoDB, cualquier expresión regular que no distinga entre mayúsculas y minúsculas no es eficiente en el índice "$ regex solo puede usar un índice de manera eficiente cuando la expresión regular tiene un ancla para el principio (es decir, ^) de una cadena y es una coincidencia que distingue entre mayúsculas y minúsculas "
Ryan Schumacher
2
Con Mongoose esto funcionó para mí: User.find ({'username': {$ regex: new RegExp ('^' + username.toLowerCase (), 'i')}}, function (err, res) {if (err ) arrojar err; siguiente (nulo, res);});
ChrisRich
5
Nunca olvides escapar del nombre cuando trabajes con expresiones regulares. No queremos que las inyecciones se apoderen de la belleza de mongodb. Imagínese que utilizó este código para una página de inicio de sesión y el nombre de usuario fue ".*".
Tobias
90
Necesitaría usar una expresión regular que no distinga entre mayúsculas y minúsculas para esta, por ejemplo
MongoDB 3.4 ahora incluye la capacidad de hacer un verdadero índice que no distingue entre mayúsculas y minúsculas, lo que aumentará drásticamente la velocidad de las búsquedas que no distinguen entre mayúsculas y minúsculas en grandes conjuntos de datos. Se realiza especificando una colación con una fuerza de 2.
Probablemente la forma más sencilla de hacerlo es establecer una intercalación en la base de datos. Entonces todas las consultas heredan esa intercalación y la usarán:
Ambas líneas no distinguen entre mayúsculas y minúsculas. El correo electrónico en la base de datos podría ser [email protected]y ambas líneas todavía encontrarán el objeto en la base de datos.
La sensibilidad a mayúsculas y minúsculas y la sensibilidad a los diacríticos se establecen en falso de forma predeterminada cuando se realizan consultas de esta manera.
Incluso puede ampliar esto seleccionando los campos que necesita del objeto de usuario de Andrew haciéndolo de esta manera:
Las expresiones regulares son más lentas que la coincidencia de cadenas literales. Sin embargo, un campo en minúsculas adicional aumentará la complejidad de su código. En caso de duda, utilice expresiones regulares. Sugeriría usar solo un campo explícitamente en minúsculas si puede reemplazar su campo, es decir, no le importa el caso en primer lugar.
Tenga en cuenta que deberá escapar del nombre antes de la expresión regular. Si desea caracteres comodín de entrada de usuario, prefiera agregar .replace(/%/g, '.*')después de escapar para que pueda hacer coincidir "a%" para encontrar todos los nombres que comienzan con 'a'.
Puede utilizar índices que no distinguen entre mayúsculas y minúsculas :
El siguiente ejemplo crea una colección sin intercalación predeterminada y 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:
Respuestas:
La solución de Chris Fulstow funcionará (+1), sin embargo, puede que no sea eficiente, especialmente si su colección es muy grande. Las expresiones regulares no arraigadas (las que no comienzan con
^
, que anclan la expresión regular al comienzo de la cadena) y las que usan lai
bandera para no distinguir entre mayúsculas y minúsculas no usarán índices, incluso si existen.Una opción alternativa que podría considerar es desnormalizar sus datos para almacenar una versión en minúscula del
name
campo, por ejemplo comoname_lower
. Luego puede consultar eso de manera eficiente (especialmente si está indexado) para coincidencias exactas que no distinguen entre mayúsculas y minúsculas, como:db.collection.find({"name_lower": thename.toLowerCase()})
O con una coincidencia de prefijo (una expresión regular arraigada) como:
db.collection.find( {"name_lower": { $regex: new RegExp("^" + thename.toLowerCase(), "i") } } );
Ambas consultas utilizarán un índice en
name_lower
.fuente
new RegExp('^'+ username + '$', "i")
para que sea una coincidencia exacta.".*"
.Necesitaría usar una expresión regular que no distinga entre mayúsculas y minúsculas para esta, por ejemplo
db.collection.find( { "name" : { $regex : /Andrew/i } } );
Para usar el patrón de expresiones regulares de su
thename
variable, construya un nuevo objeto RegExp :var thename = "Andrew"; db.collection.find( { "name" : { $regex : new RegExp(thename, "i") } } );
Actualización: para una coincidencia exacta, debe usar la expresión regular
"name": /^Andrew$/i
. Gracias a Yannick L.fuente
name
, no solo igualar.{ "name": /^Andrew$/i }
Lo he resuelto así.
var thename = 'Andrew'; db.collection.find({'name': {'$regex': thename,$options:'i'}});
Si desea realizar una consulta sobre 'concordancia exacta que no distingue entre mayúsculas y minúsculas', puede hacerlo así.
var thename = '^Andrew$'; db.collection.find({'name': {'$regex': thename,$options:'i'}});
fuente
MongoDB 3.4 ahora incluye la capacidad de hacer un verdadero índice que no distingue entre mayúsculas y minúsculas, lo que aumentará drásticamente la velocidad de las búsquedas que no distinguen entre mayúsculas y minúsculas en grandes conjuntos de datos. Se realiza especificando una colación con una fuerza de 2.
Probablemente la forma más sencilla de hacerlo es establecer una intercalación en la base de datos. Entonces todas las consultas heredan esa intercalación y la usarán:
db.createCollection("cities", { collation: { locale: 'en_US', strength: 2 } } ) db.names.createIndex( { city: 1 } ) // inherits the default collation
También puedes hacerlo así:
db.myCollection.createIndex({city: 1}, {collation: {locale: "en", strength: 2}});
Y utilícelo así:
db.myCollection.find({city: "new york"}).collation({locale: "en", strength: 2});
Esto devolverá las ciudades llamadas "nueva york", "Nueva York", "Nueva york", etc.
Para más información: https://jira.mongodb.org/browse/SERVER-90
fuente
Con Mongoose (y Node), esto funcionó:
User.find({ email: /^[email protected]$/i })
User.find({ email: new RegExp(
`^ $ {emailVariable} $`, 'i')})En MongoDB, esto funcionó:
db.users.find({ email: { $regex: /^[email protected]$/i }})
Ambas líneas no distinguen entre mayúsculas y minúsculas. El correo electrónico en la base de datos podría ser
[email protected]
y ambas líneas todavía encontrarán el objeto en la base de datos.Del mismo modo, podríamos usar
/^[email protected]$/i
y aún encontraría correo electrónico:[email protected]
en la base de datos.fuente
Para encontrar una cadena insensible a mayúsculas, use esto
var thename = "Andrew"; db.collection.find({"name":/^thename$/i})
fuente
Acabo de resolver este problema hace unas horas.
var thename = 'Andrew' db.collection.find({ $text: { $search: thename } });
Incluso puede ampliar esto seleccionando los campos que necesita del objeto de usuario de Andrew haciéndolo de esta manera:
db.collection.find({ $text: { $search: thename } }).select('age height weight');
Referencia: https://docs.mongodb.org/manual/reference/operator/query/text/#text
fuente
... con mangosta en NodeJS esa consulta:
const countryName = req.params.country; { 'country': new RegExp(`^${countryName}$`, 'i') };
o
const countryName = req.params.country; { 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } }; // ^australia$
o
const countryName = req.params.country; { 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } }; // ^turkey$
Un ejemplo de código completo en Javascript, NodeJS con Mongoose ORM en MongoDB
// get all customers that given country name app.get('/customers/country/:countryName', (req, res) => { //res.send(`Got a GET request at /customer/country/${req.params.countryName}`); const countryName = req.params.countryName; // using Regular Expression (case intensitive and equal): ^australia$ // const query = { 'country': new RegExp(`^${countryName}$`, 'i') }; // const query = { 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } }; const query = { 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } }; Customer.find(query).sort({ name: 'asc' }) .then(customers => { res.json(customers); }) .catch(error => { // error.. res.send(error.message); }); });
fuente
La siguiente consulta encontrará los documentos con la cadena requerida de forma insensible y con ocurrencia global también
db.collection.find({name:{ $regex: new RegExp(thename, "ig") } },function(err, doc) { //Your code here... });
fuente
Para buscar cadenas de literales que no distinguen entre mayúsculas y minúsculas:
Usando expresiones regulares (recomendado)
db.collection.find({ name: { $regex: new RegExp('^' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i') } });
Usar índice en minúsculas (más rápido)
db.collection.find({ name_lower: name.toLowerCase() });
Las expresiones regulares son más lentas que la coincidencia de cadenas literales. Sin embargo, un campo en minúsculas adicional aumentará la complejidad de su código. En caso de duda, utilice expresiones regulares. Sugeriría usar solo un campo explícitamente en minúsculas si puede reemplazar su campo, es decir, no le importa el caso en primer lugar.
Tenga en cuenta que deberá escapar del nombre antes de la expresión regular. Si desea caracteres comodín de entrada de usuario, prefiera agregar
.replace(/%/g, '.*')
después de escapar para que pueda hacer coincidir "a%" para encontrar todos los nombres que comienzan con 'a'.fuente
Puede utilizar índices que no distinguen entre mayúsculas y minúsculas :
El siguiente ejemplo crea una colección sin intercalación predeterminada y 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
fuente
Una forma fácil sería usar $ toLower como se muestra a continuación.
db.users.aggregate([ { $project: { name: { $toLower: "$name" } } }, { $match: { name: the_name_to_search } } ])
fuente