Comprobando si un campo contiene una cadena


454

Estoy buscando un operador, que me permita verificar si el valor de un campo contiene una cadena determinada.

Algo como:

db.users.findOne({$contains:{"username":"son"}})

¿Es eso posible?

Respuestas:


693

Puedes hacerlo con el siguiente código.

db.users.findOne({"username" : {$regex : ".*son.*"}});

16
Tenga en cuenta que esto no hará un uso eficiente de un índice y dará como resultado que se escaneen todos los valores en busca de coincidencias. Ver las notas sobre Expresiones regulares
Stennie

77
@Stennie, entonces, ¿qué sugieres para hacer un uso eficiente del índice y encontrar una subcadena?
Blue Sky

44
@Vish: si su caso de uso común es la búsqueda de texto libre de un campo y tiene una gran cantidad de documentos, tokenizaría el texto para consultas más eficientes. Podrías usar multikeys para una búsqueda simple de texto completo, o tal vez construir un índice invertido como una colección separada. Para búsquedas poco frecuentes o una pequeña colección de documentos, escanear el índice completo puede ser un rendimiento aceptable (aunque no óptimo).
Stennie

98
¿No es esto una exageración? Lo que quieres es db.users.findOne({"username" : {$regex : "son"}});
JamieJag

3
Es posible que desee consultar la búsqueda de texto completo en Mongo 2.6
wprl

179

Como Mongo shell admite regex, eso es completamente posible.

db.users.findOne({"username" : /.*son.*/});

Si queremos que la consulta no distinga entre mayúsculas y minúsculas, podemos usar la opción "i", como se muestra a continuación:

db.users.findOne({"username" : /.*son.*/i});

Ver: http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-RegularExpressions


1
Incluya un fragmento de código que demuestre el uso de expresiones regulares para la búsqueda. Las respuestas deben incluir más información que un simple enlace ...
maerics

1
La respuesta seleccionada no funcionó para mí, pero esta sí (estoy ejecutando consultas mongo a través de los comandos de Docker Exec) Creo que esta debería ser la respuesta seleccionada porque parece ser más versátil.
Arthur Weborg

55
como los comentarios en la respuesta seleccionada, creo db.users.findOne({"username" : /.*son.*/});que también podría ser exagerado y la expresión regular podría ser simple/son/
Arthur Weborg

2
Forma

44
Edite esto para usarlo solo{ username: /son/ }
Wyck

150

https://docs.mongodb.com/manual/reference/sql-comparison/

http://php.net/manual/en/mongo.sqltomongo.php

MySQL

SELECT * FROM users WHERE username LIKE "%Son%"

MongoDB

db.users.find({username:/Son/})

8
Su respuesta MongoDB es buena; considere editar su pregunta para eliminar los consejos irrelevantes de MySQL.
Maerics

31
¿Eliminar todas las consultas o cambiarlas? SQL más conocido, es útil para comprender MongoDB
Zheng Kai

44
@ZhengKai: en este sitio web, por lo general, debe responder la pregunta directamente, utilizando solo las tecnologías específicas etiquetadas y solicitadas.
Maerics

98
@maerics personalmente encontré que la inclusión de MySQL de Zheng fue muy útil ya que proporcionaba un punto de referencia.
Mike Bartlett

50
También encontré relevante la referencia SQL, creo que debería permanecer.
vikingsteve

69

A partir de la versión 2.4, puede crear un índice de texto en los campos para buscar y usar el operador $ text para realizar consultas.

Primero, cree el índice:

db.users.createIndex( { "username": "text" } )

Luego, para buscar:

db.users.find( { $text: { $search: "son" } } )

Puntos de referencia (~ 150K documentos):

  • Regex (otras respuestas) => 5.6-6.9 segundos
  • Búsqueda de texto => .164-.201 segundos

Notas:

  • Una colección solo puede tener un índice de texto. Puede utilizar un índice de texto comodín si desea buscar en cualquier campo de cadena, así: db.collection.createIndex( { "$**": "text" } ).
  • Un índice de texto puede ser grande. Contiene una entrada de índice para cada palabra post-raíz única en cada campo indexado para cada documento insertado.
  • La creación de un índice de texto tardará más que un índice normal.
  • Un índice de texto no almacena frases o información sobre la proximidad de las palabras en los documentos. Como resultado, las consultas de frases se ejecutarán de manera mucho más efectiva cuando toda la colección encaje en la RAM.

14
no, el operador de texto de hecho no permite ejecutar "contiene", por lo que solo devolverá la coincidencia exacta de palabras, la única opción actualmente a partir de 3.0 es usar regex, es decir, db.users.find ({nombre de usuario: / son / i} ) éste looksup cada usuario que contiene "hijo" (caso-insenstive)
comeGetSome

3
¿Tiene que reindexar cuando agrega o elimina documentos a / de la colección?
Jake Wilson

El título de la pregunta dice "contiene". la búsqueda de texto completo no es aplicable a la pregunta.
Donato

29

Como este es uno de los primeros éxitos en los motores de búsqueda, y ninguno de los anteriores parece funcionar para MongoDB 3.x, aquí hay una búsqueda de expresiones regulares que funciona:

db.users.find( { 'name' : { '$regex' : yourvalue, '$options' : 'i' } } )

No es necesario crear un índice adicional o similar.


1
Las expresiones regulares necesitan ser desinfectadas.
sean

16

Esto es lo que debe hacer si está conectando MongoDB a través de Python

db.users.find({"username": {'$regex' : '.*' + 'Son' + '.*'}})

También puede usar un nombre de variable en lugar de 'Hijo' y, por lo tanto, la concatenación de cadenas.


en es2015 puede usar los backticks {$ regex: .*${value}.*}
Michael Guild

16

La forma más sencilla de realizar esta tarea

Si desea que la consulta distinga entre mayúsculas y minúsculas

db.getCollection("users").find({'username':/Son/})

Si desea que la consulta no distinga entre mayúsculas y minúsculas

db.getCollection("users").find({'username':/Son/i})

1
¿Cómo usar variable con regex?
Hisham

4

respuesta ideal su índice de uso i opción para mayúsculas y minúsculas

db.users.findOne({"username" : new RegExp(search_value, 'i') });

Las expresiones regulares necesitan ser desinfectadas.
sean


1

Cómo ignorar las etiquetas HTML en una coincidencia RegExp:

var text = '<p>The <b>tiger</b> (<i>Panthera tigris</i>) is the largest <a href="https://stackoverflow.com/wiki/Felidae" title="Felidae">cat</a> <a href="https://stackoverflow.com/wiki/Species" title="Species">species</a>, most recognizable for its pattern of dark vertical stripes on reddish-orange fur with a lighter underside. The species is classified in the genus <i><a href="https://stackoverflow.com/wiki/Panthera" title="Panthera">Panthera</a></i> with the <a href="https://stackoverflow.com/wiki/Lion" title="Lion">lion</a>, <a href="https://stackoverflow.com/wiki/Leopard" title="Leopard">leopard</a>, <a href="https://stackoverflow.com/wiki/Jaguar" title="Jaguar">jaguar</a>, and <a href="https://stackoverflow.com/wiki/Snow_leopard" title="Snow leopard">snow leopard</a>. It is an <a href="https://stackoverflow.com/wiki/Apex_predator" title="Apex predator">apex predator</a>, primarily preying on <a href="https://stackoverflow.com/wiki/Ungulate" title="Ungulate">ungulates</a> such as <a href="https://stackoverflow.com/wiki/Deer" title="Deer">deer</a> and <a href="https://stackoverflow.com/wiki/Bovid" class="mw-redirect" title="Bovid">bovids</a>.</p>';
var searchString = 'largest cat species';

var rx = '';
searchString.split(' ').forEach(e => {
  rx += '('+e+')((?:\\s*(?:<\/?\\w[^<>]*>)?\\s*)*)';
});

rx = new RegExp(rx, 'igm');

console.log(text.match(rx));

Probablemente sea muy fácil convertirlo en un filtro de agregación MongoDB.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.