¿Cómo consultar MongoDB con "me gusta"?

1437

Quiero consultar algo con la likeconsulta de SQL :

SELECT * FROM users  WHERE name LIKE '%m%'

¿Cómo hago para lograr lo mismo en MongoDB? No puedo encontrar un operador likeen la documentación .

Viento libre
fuente
77
ver los documentos de mongodb: Consultas avanzadas - Expresiones regulares mongodb.org/display/DOCS/…
douyw
77
Su pregunta tiene al menos 5votos para la etiqueta de operador similar . ¿Podría solicitar amablemente que sugiera sql-like como sinónimo ?
Kermit
3
Este enlace puede ayudarte a goo.gl/gdTYK8
Dilip Kr Singh

Respuestas:

1945

Eso tendría que ser:

db.users.find({"name": /.*m.*/})

o similar:

db.users.find({"name": /m/})

Está buscando algo que contenga "m" en alguna parte (el %operador ' ' de SQL es equivalente a ' .*' de Regexp ), no algo que tenga "m" anclado al comienzo de la cadena.

nota: mongodb usa expresiones regulares que son más poderosas que "LIKE" en sql. Con expresiones regulares puedes crear cualquier patrón que imagines.

Para obtener más información sobre expresiones regulares, consulte este enlace https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

Kyle H
fuente
96
¿Es caro buscar por expresiones regulares?
Freewind
147
En realidad, depende. Si la consulta no usa un índice y debe hacer un escaneo de tabla, entonces ciertamente puede ser costoso. Si está haciendo una consulta de expresiones regulares 'comienza con', entonces eso puede usar un índice. Lo mejor es ejecutar un explicar () para ver qué sucede.
Kyle Banker
35
Cuando no está anclado al comienzo de la cuerda, es algo costoso. Pero, de nuevo, también lo es una LIKEconsulta en SQL.
Emily
44
entonces, siempre y cuando esté anclado al comienzo de la cuerda, ¿está bien? genial entonces. ¿eso significa que necesitamos agregar ^
user4951
44
Agregaría regex ijavascript db.users.find({ "name": { $regex: /m/i } })
Doron Segal
368
db.users.insert({name: 'paulo'})
db.users.insert({name: 'patric'})
db.users.insert({name: 'pedro'})

db.users.find({name: /a/})  //like '%a%'

fuera: paulo, patric

db.users.find({name: /^pa/}) //like 'pa%' 

fuera: paulo, patric

db.users.find({name: /ro$/}) //like '%ro'

fuera: pedro

Johnathan Douglas
fuente
buen ejemplo! Estoy encontrando el final del cheque con espacio y encontré esto :) / $ /
Phuong
¿Cómo encuentras todas las entradas para el nombre? o el comodín para * en SQL? ¿Algo que hace select name from users;que solo enumera a todos los usuarios?
anon58192932
1
@ anon58192932 Para mostrar todas las entradas de solo el campo "nombre" en una tabla llamada "usuarios", puede usar el método project () estableciendo los valores de los campos que desea 1. Los campos que no se mencionan en project () no serán traído excepto _id. El campo _id se imprime de forma predeterminada, lo que puede suprimir al poner el valor 0 para _id dentro del método project (). Algo así como: db.collection.find (). Project ({name: 1, _id: 0}) .toArray (function (err, docs) {console.log (docs); callback (docs);}); Consulte esto: docs.mongodb.com/manual/tutorial/…
gauravparmar
282

En

  • PyMongo usando Python
  • Mangosta usando Node.js
  • Jongo , usando Java
  • mgo , usando Go

tu puedes hacer:

db.users.find({'name': {'$regex': 'sometext'}})
Afshin Mehrabani
fuente
2
funciona bien para la búsqueda entre mayúsculas y minúsculas, ¿podría decirme cómo puedo hacer que funcione para realizar una búsqueda que no distingue entre mayúsculas y minúsculas?
Tahir Yasin
Para qué sería la expresión regular%sometext%
Tahir Yasin
64
@TahirYasin si todavía te estás preguntando, la búsqueda que no distingue entre mayúsculas y minúsculas se haría así:db.users.find({'name': {'$regex': 'sometext', '$options': 'i'}})
sumowrestler
Resolví en golang usando mgo simplemente código como este, selector: = bson.M {"technician": bson.M {"$ regex": tech}}
Sandun Priyanka
1
Siente que esta debería ser la respuesta aceptada. Es el más simple y elegante actualmente.
Brett84c
88

En PHP, puede usar el siguiente código:

$collection->find(array('name'=> array('$regex' => 'm'));
León
fuente
44
python + mongoengine: people = People.objects.raw_query ({'name': {'$ regex': 'm'}})
panchicore
1
Si su valor RegEx se origina a partir de la entrada del usuario (por ejemplo, un formulario de filtro) y no desea que el valor mismo se tome como un RegExp, puede aplicar preg_quote ().
Philipp Rieber
2
Me acabo de dar cuenta de esto, pero en realidad esta es la respuesta incorrecta, a pesar de que funciona es subóptimo, en su lugar debería usar el objeto de expresión regular BSON a través de MongoRegex, $ regex tiene problemas de compatibilidad con ciertos comandos como $ in
Sammaye
Esta sintaxis es útil si el valor se almacena en una variable, por lo que la consulta podría escribirse como (en Ruby):$collection.where(field => {"$regex" => value})
Donny Kurnia
Pero, ¿por qué no puedes usar literales de matriz?
Alper
53

Usarías regex para eso en mongo.

p.ej: db.users.find({"name": /^m/})

Joshua Partogi
fuente
29
Creo que esto solo muestra documentos con un valor de nombre que comienza con "m"
JackAce
53

Ya hay muchas respuestas. Estoy dando diferentes tipos de requisitos y soluciones para la búsqueda de cadenas con expresiones regulares.

Puede hacerlo con expresiones regulares que contienen palabras, es decir, me gusta. También puede usar $options => ipara la búsqueda sin distinción entre mayúsculas y minúsculas

Contiene string

db.collection.find({name:{'$regex' : 'string', '$options' : 'i'}})

No contiene stringsolo con expresiones regulares

db.collection.find({name:{'$regex' : '^((?!string).)*$', '$options' : 'i'}})

Caso exacto insensible string

db.collection.find({name:{'$regex' : '^string$', '$options' : 'i'}})

Empezar con string

db.collection.find({name:{'$regex' : '^string', '$options' : 'i'}})

Terminar con string

db.collection.find({name:{'$regex' : 'string$', '$options' : 'i'}})

Conserve esto como un marcador y como referencia para cualquier otra modificación que pueda necesitar.

Somnath Muluk
fuente
37

Tienes 2 opciones:

db.users.find({"name": /string/})

o

db.users.find({"name": {"$regex": "string", "$options": "i"}})

En el segundo, tiene más opciones, como "i" en las opciones para encontrar usando mayúsculas y minúsculas. Y sobre la "cadena", puede usar como ". Cadena " (% cadena%) o "cadena. *" (Cadena%) y ". * Cadena) (% cadena) por ejemplo. Puede usar expresiones regulares como tu quieras

¡Disfrutar!

usuario3645907
fuente
34

Si el uso de Node.js , se dice que se puede escribir lo siguiente:

db.collection.find( { field: /acme.*corp/i } );
//or
db.collection.find( { field: { $regex: 'acme.*corp', $options: 'i' } } );

Además , puedes escribir esto:

db.collection.find( { field: new RegExp('acme.*corp', 'i') } );
Remolino
fuente
Sintaxis similar en Ruby:collection.where(field => Regexp.new(value))
Donny Kurnia
24

Ya tienes las respuestas, pero para que coincida la expresión regular con insensibilidad a mayúsculas y minúsculas

Puedes usar la siguiente consulta

db.users.find ({ "name" : /m/i } ).pretty()

En iel /m/icaso indica insensibilidad al caso y .pretty()proporciona una salida más bonita

El sexto sentido
fuente
pero ¿qué pasa si quiero establecer el valor dinámicamente aquí
KS
@KuldeepKoranga puede colocar cualquier valor dinámico en lugar de 'm'. Es eso lo que quieres.
The6thSense
var search="feacebook"Entonces, db.users.find ({ "name" : /search/i } )¿ cómo puedo configurar a continuación @ The6thSens Sí, pero ?
KS
@KuldeepKoranga tiene asignado el valor.
The6thSense
1
@KuldeepKoranga stackoverflow.com/questions/7790811/… ¿esto ayuda?
The6thSense
18

Para Mangosta en Node.js

db.users.find({'name': {'$regex': '.*sometext.*'}})
Aqib Mumtaz
fuente
13

Puede usar la nueva característica de 2.6 mongodb:

db.foo.insert({desc: "This is a string with text"});
db.foo.insert({desc:"This is a another string with Text"});
db.foo.ensureIndex({"desc":"text"});
db.foo.find({
    $text:{
        $search:"text"
    }
});
cmarrero01
fuente
66
Tenga en cuenta que la búsqueda de texto de AFAIK Mongodb funciona en palabras completas solo de forma predeterminada, por lo que coincidirá con valores como "Esta es una cadena con texto", pero no "Esta es una cadena con subtexto". Entonces no es como el operador "LIKE" de sql.
rocketmonkeys
@Rocketmonkeys es verdad ... para algo como "operador LIKE" usarías el operador $ regex mongo.
cmarrero01
13

En el proyecto nodejs y use mangosta, use Like query

var User = mongoose.model('User');

var searchQuery={};
searchQuery.email = req.query.email;
searchQuery.name = {$regex: req.query.name, $options: 'i'};
User.find(searchQuery, function(error, user) {
                if(error || user === null) {
                    return res.status(500).send(error);
                }
                return res.status(200).send(user);
            });
Shaishab Roy
fuente
¿Cómo puedo usar como consulta? He intentado esto pero no funciona:searchQuery.product_name = '/'+req.query.search.value+'/i';
Muhammad Shahzad
puede intentarlo como:searchQuery.product_name= {$regex: req.query.search.value, $options: 'i'};
Shaishab Roy
Me salvas la vida, amigo. ¿Puedes explicarme poco qué es $ regex y $ opciones?
Muhammad Shahzad
if(req.query.search.value){ searchQuery.product_name = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_amount = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_person = {$regex: req.query.search.value, $options: 'i'}; searchQuery.department_name = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_date = {$regex: req.query.search.value, $options: 'i'}; }¿Puedes ver por qué esto no funciona?
Muhammad Shahzad
así $regex: 'value' generar una expresión regular para el valor de búsqueda y $options: 'i'medios entre mayúsculas y minúsculas . Su código no funcionó debido a que utilizó mismo valor para diferentes propiedades y que actúan como y condición que no debe cumplir con su colección de base de datos.
Shaishab Roy
12

Para PHP Mongo Like.
Tuve varios problemas con php mongo como. descubrí que la concatenación de los parámetros de expresiones regulares ayuda en algunas situaciones con las que comienza PHP mongo find field . Pensé que publicaría aquí para contribuir al hilo más popular

p.ej

db()->users->insert(['name' => 'john']);
db()->users->insert(['name' => 'joe']);
db()->users->insert(['name' => 'jason']);

// starts with
$like_var = 'jo';
$prefix = '/^';
$suffix = '/';
$name = $prefix . $like_var . $suffix;
db()->users->find(['name' => array('$regex'=>new MongoRegex($name))]);
output: (joe, john)

// contains
$like_var = 'j';
$prefix = '/';
$suffix = '/';
$name = $prefix . $like_var . $suffix;
db()->users->find(['name' => array('$regex'=>new MongoRegex($name))]);

output: (joe, john, jason)
Salto
fuente
Según las respuestas y comentarios anteriores, la búsqueda $ text (Index) dará una mejor solución con el punto de referencia en comparación con el método $ regex correcto. Para referencia, consulte este enlace stackoverflow.com/questions/10610131/… . ¿Es posible implementar el método de índice $ text con PHP y mongoDB?
sankar muniyappa
12

Usar plantillas literales con variables también funciona:

{"firstname": {$regex : `^${req.body.firstname}.*` , $options: 'si' }}

besthost
fuente
Esta es la búsqueda desde el inicio ex - si "firstname" contiene testlast y si busco por "last" no dará resultado.
Vikas Chauhan
11

Con MongoDB Compass, debe usar la sintaxis de modo estricto, como tal:

{ "text": { "$regex": "^Foo.*", "$options": "i" } }

(En MongoDB Compass, es importante que use en "lugar de ')

maldito
fuente
10

Puede usar la instrucción where para construir cualquier script JS:

db.myCollection.find( { $where: "this.name.toLowerCase().indexOf('m') >= 0" } );

Referencia: http://docs.mongodb.org/manual/reference/operator/where/

briba
fuente
99
$whereEs altamente ineficiente. Hacer un análisis completo de la colección :(
Sushant Gupta
ah, no hay problema, estaba diciendo así: D
Sushant Gupta
10

En SQL, la consulta 'me gusta ' se ve así:

select * from users where name like '%m%'

En la consola MongoDB, se ve así:

db.users.find({"name": /m/})     // Not JSON formatted

db.users.find({"name": /m/}).pretty()  // JSON formatted

Además, el pretty()método incluirá en todos los lugares donde se produzca una estructura JSON formateada que sea más legible.

MADHAIYAN M
fuente
10

Regex son caros son proceso.

Otra forma es crear un índice de texto y luego buscarlo usando $search.

Cree un índice de texto de los campos que desea que se puedan buscar:

db.collection.createIndex({name: 'text', otherField: 'text'});

Busque una cadena en el índice de texto:

db.collection.find({
  '$text'=>{'$search': "The string"}
})
Oxido
fuente
Solución perfecta ... Las expresiones regulares son demasiado caras. Trabajando con un conjunto de datos de 20 millones de documentos y la diferencia de rendimiento es muy muy notable (lo cual es un eufemismo)
nivensookharan
1
De hecho, esto solo funciona para palabras completas, ver docs.mongodb.com/manual/core/index-text/#index-entries
Thomas Ebert
8

En Go y el controlador mgo:

Collection.Find(bson.M{"name": bson.RegEx{"m", ""}}).All(&result)

donde resultado es la instancia de estructura del tipo buscado


fuente
2
pls evitar campos sin codificar en los literales, no bson:RegEx{Pattern:"m", Options:"i"}en su lugar
bithavoc
8

Use expresiones regulares que coincidan como a continuación. La 'i' muestra insensibilidad a mayúsculas y minúsculas.

var collections = mongoDatabase.GetCollection("Abcd");

var queryA = Query.And(
         Query.Matches("strName", new BsonRegularExpression("ABCD", "i")), 
         Query.Matches("strVal", new BsonRegularExpression("4121", "i")));

var queryB = Query.Or(
       Query.Matches("strName", new BsonRegularExpression("ABCD","i")),
       Query.Matches("strVal", new BsonRegularExpression("33156", "i")));

var getA = collections.Find(queryA);
var getB = collections.Find(queryB);
Shalabh Raizada
fuente
6

Like Mery sería como se muestra a continuación

db.movies.find({title: /.*Twelve Monkeys.*/}).sort({regularizedCorRelation : 1}).limit(10);

para scala ReactiveMongo api,

val query = BSONDocument("title" -> BSONRegex(".*"+name+".*", "")) //like
val sortQ = BSONDocument("regularizedCorRelation" -> BSONInteger(1))
val cursor = collection.find(query).sort(sortQ).options(QueryOpts().batchSize(10)).cursor[BSONDocument]
prayagupd
fuente
6

Parece que hay razones para usar tanto el /regex_pattern/patrón javascript como el {'$regex': 'regex_pattern'}patrón mongo . Ver: Restricciones de sintaxis de RegEx de MongoBD

Este no es un tutorial completo de RegEx, pero me inspiré para ejecutar estas pruebas después de ver una publicación ambigua muy votada arriba .

> ['abbbb','bbabb','bbbba'].forEach(function(v){db.test_collection.insert({val: v})})

> db.test_collection.find({val: /a/})
{ "val" : "abbbb" }
{ "val" : "bbabb" }
{ "val" : "bbbba" }

> db.test_collection.find({val: /.*a.*/})
{ "val" : "abbbb" }
{ "val" : "bbabb" }
{ "val" : "bbbba" }

> db.test_collection.find({val: /.+a.+/})
{ "val" : "bbabb" }

> db.test_collection.find({val: /^a/})
{ "val" : "abbbb" }

> db.test_collection.find({val: /a$/})
{ "val" : "bbbba" }

> db.test_collection.find({val: {'$regex': 'a$'}})
{ "val" : "bbbba" }
Bruno Bronosky
fuente
5

Si está utilizando Spring-Data Mongodb, puede hacerlo de esta manera:

String tagName = "m";
Query query = new Query();
query.limit(10);        
query.addCriteria(Criteria.where("tagName").regex(tagName));
Vaibhav
fuente
4

Como Mongo shell admite regex, eso es completamente posible.

db.users.findOne({"name" : /.*sometext.*/});

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({"name" : /.*sometext.*/i});
sravanthi
fuente
4

Utilice la búsqueda de subcadenas de agregación (con índice !!!):

db.collection.aggregate([{
        $project : {
            fieldExists : {
                $indexOfBytes : ['$field', 'string']
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }, {
        $limit : 5
    }
]);
kz_sergey
fuente
¡bonito! ¿Hay alguna manera de hacer coincidir todo el documento? o hacer que el marco de agregación haga una consulta de seguimiento para hacer eso? Por el momento se ve un partido:{ "_id" : ObjectId("5aba5ad988385120a01b1ac2"), "fieldExists" : 4 }
Gianfranco P.
en $ etapa del proyecto solo proyecta lo que quieres
Vokail
4

Cadena deepakparmar, dipak, parmar

db.getCollection('yourdb').find({"name":/^dee/})

ans deepakparmar

db.getCollection('yourdb').find({"name":/d/})

ans deepakparmar, dipak

db.getCollection('yourdb').find({"name":/mar$/})

ans deepakparmar, parmar

Deepak Parmar
fuente
2

Encontré una herramienta gratuita para traducir consultas MYSQL a MongoDB. http://www.querymongo.com/ Lo comprobé con varias consultas. como veo casi todos ellos son correctos. Según eso, la respuesta es

db.users.find({
    "name": "%m%"
});
Vitanage Lakmal
fuente
2

MongoRegex ha quedado en desuso.
Utilice MongoDB \ BSON \ Regex

$regex = new MongoDB\BSON\Regex ( '^m');
$cursor = $collection->find(array('users' => $regex));
//iterate through the cursor
Albert s
fuente
Es importante tener en cuenta que esto se refiere a la clase MongoRegex en PHP . No es muy relevante para esta pregunta que trata sobre Node. Esto probablemente debería ser un comentario o mejor aún: una pregunta auto respondida en una publicación separada.
Boaz - Restablece a Mónica
2
db.customer.find({"customerid": {"$regex": "CU_00000*", "$options": "i"}}).pretty()

Cuando buscamos patrones de cadena, siempre es mejor usar el patrón anterior como cuando no estamos seguros del caso. ¡¡¡Espero que ayude!!!

priya raj
fuente