Comment interroger MongoDB avec "j'aime"?

1437

Je veux interroger quelque chose avec la likerequête SQL :

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

Comment puis-je obtenir la même chose dans MongoDB? Je ne trouve pas d'opérateur likedans la documentation .

Freewind
la source
7
voir les documents de mongodb: Advanced Queries - Expressions régulières mongodb.org/display/DOCS/…
douyw
7
Votre question a au moins des 5votes pour le tag d' opérateur similaire . Puis-je vous demander de suggérer comme sql-like comme synonyme ?
Kermit
3
Ce lien peut vous aider goo.gl/gdTYK8
Dilip Kr Singh

Réponses:

1945

Cela devrait être:

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

ou similaire:

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

Vous recherchez quelque chose qui contient «m» quelque part (l' %opérateur « » de SQL est équivalent à « .*» de Regexp ), pas quelque chose qui a «m» ancré au début de la chaîne.

note: mongodb utilise des expressions régulières plus puissantes que "LIKE" en sql. Avec des expressions régulières, vous pouvez créer n'importe quel motif que vous imaginez.

Pour plus d'informations sur les expressions régulières, reportez-vous à ce lien https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

Kyle H
la source
96
la recherche par expression régulière coûte-t-elle cher?
Freewind du
147
En fait, cela dépend. Si la requête n'utilise pas d'index et doit effectuer une analyse de table, cela peut certainement être coûteux. Si vous faites une requête regex «commence par», cela peut utiliser un index. Il est préférable d'exécuter une explication () pour voir ce qui se passe.
Kyle Banker
35
Lorsqu'il n'est pas ancré au début de la chaîne, c'est un peu cher. Mais là encore, il en va de même pour une LIKErequête en SQL.
Emily
4
donc tant qu'il est ancré au début de la chaîne, ça va? cool alors. cela signifie-t-il que nous devons ajouter ^
user4951
44
J'ajouterais 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%'

sortie: paulo, patric

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

sortie: paulo, patric

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

sortie: pedro

Johnathan Douglas
la source
bel exemple! Je trouve la fin du chèque avec de l'espace et j'ai trouvé ça :) / $ /
Phuong
comment trouvez-vous toutes les entrées pour le nom? ou le caractère générique pour * en SQL? Quelque chose qui fait select name from users;qui répertorie tous les utilisateurs?
anon58192932
1
@ anon58192932 Pour afficher toutes les entrées du champ "nom" uniquement dans une table nommée "utilisateurs", vous pouvez utiliser la méthode project () en définissant les valeurs des champs que vous souhaitez 1. Les champs qui ne sont pas mentionnés dans project () ne seront pas récupéré sauf _id. Le champ _id est imprimé par défaut que vous pouvez supprimer en mettant la valeur 0 pour _id à l'intérieur de la méthode project (). Quelque chose comme - db.collection.find (). Project ({name: 1, _id: 0}) .toArray (function (err, docs) {console.log (docs); callback (docs);}); Référer ceci - docs.mongodb.com/manual/tutorial/…
gauravparmar
282

Dans

  • PyMongo utilisant Python
  • Mangouste utilisant Node.js
  • Jongo , en utilisant Java
  • mgo , en utilisant Go

tu peux faire:

db.users.find({'name': {'$regex': 'sometext'}})
Afshin Mehrabani
la source
2
cela fonctionne bien pour la recherche sensible à la casse, pourriez-vous s'il vous plaît me dire comment puis-je faire en sorte que la recherche ne respecte pas la casse?
Tahir Yasin
Quel serait le regex pour%sometext%
Tahir Yasin
64
@TahirYasin si vous vous demandez toujours, la recherche insensible à la casse se ferait comme ceci:db.users.find({'name': {'$regex': 'sometext', '$options': 'i'}})
sumowrestler
J'ai résolu dans golang en utilisant mgo simplement du code comme celui-ci, sélecteur: = bson.M {"technicien": bson.M {"$ regex": tech}}
Sandun Priyanka
1
Sentez-vous que cela devrait être la réponse acceptée. C'est le plus simple et le plus élégant actuellement.
Brett84c
88

En PHP, vous pouvez utiliser le code suivant:

$collection->find(array('name'=> array('$regex' => 'm'));
leon
la source
4
python + mongoengine: people = People.objects.raw_query ({'name': {'$ regex': 'm'}})
panchicore
1
Si votre valeur RegEx provient d'une entrée utilisateur (par exemple un formulaire de filtre) et que vous ne voulez pas que la valeur elle-même soit prise comme RegExp, vous pouvez lui appliquer preg_quote ().
Philipp Rieber
2
Je viens de m'en rendre compte, mais c'est en fait la mauvaise réponse, même si cela fonctionne, il est sous-optimal, vous devriez plutôt utiliser l'objet regex BSON réel via MongoRegex, $ regex a des problèmes de compatibilité avec certaines commandes comme $ in
Sammaye
Cette syntaxe est utile si la valeur est stockée dans une variable, donc la requête pourrait être écrite comme (en Ruby):$collection.where(field => {"$regex" => value})
Donny Kurnia
Mais pourquoi ne pouvez-vous pas utiliser des littéraux de tableau?
Alper
53

Vous utiliseriez regex pour cela en mongo.

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

Joshua Partogi
la source
29
Je pense que cela ne montre que les documents dont la valeur de nom commence par "m"
JackAce
53

Il existe déjà de nombreuses réponses. Je donne différents types d'exigences et de solutions pour la recherche de chaînes avec regex.

Vous pouvez le faire avec des expressions rationnelles qui contiennent des mots ie comme. Vous pouvez également utiliser $options => ipour la recherche insensible à la casse

Contient string

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

Ne contient pas stringuniquement avec regex

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

Insensible à la casse exacte string

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

Commencer avec string

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

Terminer par string

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

Conservez -le comme un signet et une référence pour toute autre modification dont vous pourriez avoir besoin.

Somnath Muluk
la source
37

Vous avez 2 choix:

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

ou

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

Sur le second, vous avez plus d'options, comme "i" dans les options pour trouver en utilisant la casse. Et à propos de la "chaîne", vous pouvez utiliser comme ". Chaîne. " (% Chaîne%), ou "chaîne. *" (Chaîne%) et ". * Chaîne) (% chaîne) par exemple. Vous pouvez utiliser l'expression régulière comme tu veux.

Prendre plaisir!

user3645907
la source
34

Si vous utilisez node.js , il est écrit que vous pouvez écrire ceci:

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

En outre , vous pouvez écrire ceci:

db.collection.find( { field: new RegExp('acme.*corp', 'i') } );
Tourbillon
la source
Syntaxe similaire dans Ruby:collection.where(field => Regexp.new(value))
Donny Kurnia
24

Vous avez déjà obtenu les réponses, mais pour faire correspondre l'expression rationnelle avec l'insensibilité à la casse

Vous pouvez utiliser la requête suivante

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

Le idans le /m/iindique une insensibilité à la casse et .pretty()fournit une sortie plus jolie

The6thSense
la source
mais que faire si je veux définir une valeur dynamiquement ici
KS
@KuldeepKoranga, vous pouvez placer n'importe quelle valeur dynamique à la place de «m». Est-ce que c'est ce que tu veux.
The6thSense
var search="feacebook"alors comment puis-je définir ci-dessous @ The6thSens Oui, mais db.users.find ({ "name" : /search/i } )?
KS
@KuldeepKoranga vous avez assigné la valeur.
The6thSense
1
@KuldeepKoranga stackoverflow.com/questions/7790811/… fait cette aide
The6thSense
18

Pour Mongoose dans Node.js

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

Vous pouvez utiliser la nouvelle fonctionnalité 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
la source
6
Notez que la recherche de texte d'AFAIK Mongodb ne fonctionne que sur des mots entiers par défaut, donc cela correspondra à des valeurs comme "Ceci est une chaîne avec du texte", mais pas "Ceci est une chaîne avec du sous-texte". Ce n'est donc pas tout à fait comme l'opérateur "LIKE" de sql.
rocketmonkeys
@Rocketmonkeys c'est vrai .. pour quelque chose comme "opérateur LIKE", vous utiliseriez l'opérateur $ regex mongo.
cmarrero01
13

Dans le projet nodejs et utilisez mangouste, utilisez la requête Like

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
la source
Comment puis-je utiliser comme requête? J'ai essayé cela mais ne fonctionne pas:searchQuery.product_name = '/'+req.query.search.value+'/i';
Muhammad Shahzad
peut essayer comme:searchQuery.product_name= {$regex: req.query.search.value, $options: 'i'};
Shaishab Roy
Tu me sauves la vie mec. pouvez-vous expliquer peu ce qu'est $ regex et $ options?
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'}; }pouvez-vous voir pourquoi cela ne fonctionne pas?
Muhammad Shahzad
bien $regex: 'value' générer une expression régulière pour votre valeur de recherche et $options: 'i'signifie insensible à la casse . Votre code n'a pas travaillé à cause de vous utilisé même valeur pour différents biens et qui agissent comme et la condition qui ne devrait pas remplir avec votre collection de base de données.
Shaishab Roy
12

Pour PHP mongo Like.
J'ai eu plusieurs problèmes avec php mongo comme. J'ai trouvé que la concaténation des paramètres regex aide dans certaines situations, le champ de recherche PHP mongo commence par . Je pensais que je posterais ici pour contribuer au fil le plus populaire

par exemple

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)
Dap
la source
Selon les réponses et commentaires précédents, la recherche $ text (Index) donnera une meilleure solution avec un benchmark comparé à la méthode $ regex. Pour référence, consultez ce lien stackoverflow.com/questions/10610131/… . Est-il possible d'implémenter la méthode $ text index avec PHP et mongoDB
sankar muniyappa
12

L'utilisation de littéraux de modèle avec des variables fonctionne également:

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

besthost
la source
C'est la recherche depuis le début ex - si "prénom" contient testlast et si je recherche par "dernier" il ne donnera pas de résultat.
Vikas Chauhan
11

Avec MongoDB Compass, vous devez utiliser la syntaxe de mode strict, en tant que telle:

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

(Dans MongoDB Compass, il est important que vous utilisiez "au lieu de ')

merde
la source
10

Vous pouvez utiliser l'instruction where pour créer n'importe quel script JS:

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

Référence: http://docs.mongodb.org/manual/reference/operator/where/

briba
la source
9
$whereest très inefficace. Faire une analyse complète de la collection :(
Sushant Gupta
ah, pas de problème, je disais juste comme ça: D
Sushant Gupta
10

En SQL, la requête ' like ' ressemble à ceci:

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

Dans la console MongoDB, cela ressemble à ceci:

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

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

En outre, la pretty()méthode produira à tous les endroits où la structure JSON formatée sera plus lisible.

MADHAIYAN M
la source
10

Les regex coûtent cher.

Une autre façon consiste à créer un index de texte, puis à le rechercher à l'aide de $search.

Créez un index de texte des champs que vous souhaitez rendre consultable:

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

Recherchez une chaîne dans l'index de texte:

db.collection.find({
  '$text'=>{'$search': "The string"}
})
Rouille
la source
Solution parfaite ... Les Regex sont trop chères. Travailler avec un ensemble de données de 20 millions de documents et la différence de performance est très très perceptible (ce qui est un euphémisme)
nivensookharan
1
En effet, cela ne fonctionne que pour des mots entiers, voir docs.mongodb.com/manual/core/index-text/#index-entries
Thomas Ebert
8

Dans Go et le pilote mgo:

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

où result est l'instance struct du type recherché


la source
2
les pls évitent les champs sans clé dans les littéraux, faites à la bson:RegEx{Pattern:"m", Options:"i"}place
bithavoc
8

Utilisez des expressions régulières correspondant comme ci-dessous. Le «i» montre une insensibilité à la casse.

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
la source
6

Comme la requête serait comme indiqué ci-dessous

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

pour 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
la source
6

Il semble qu'il y ait des raisons d'utiliser à la fois le /regex_pattern/modèle javascript et le {'$regex': 'regex_pattern'}modèle mongo . Voir: Restrictions de la syntaxe MongoBD RegEx

Ce n'est pas un tutoriel RegEx complet, mais j'ai été inspiré pour exécuter ces tests après avoir vu un post ambigu très voté ci-dessus .

> ['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
la source
5

Si vous utilisez Spring-Data Mongodb Vous pouvez le faire de cette façon:

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

Comme le shell Mongo supporte les regex, c'est tout à fait possible.

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

Si nous voulons que la requête soit insensible à la casse, nous pouvons utiliser l'option "i", comme indiqué ci-dessous:

db.users.findOne({"name" : /.*sometext.*/i});
sravanthi
la source
4

Utilisez la recherche de sous-chaîne d'agrégation (avec index !!!):

db.collection.aggregate([{
        $project : {
            fieldExists : {
                $indexOfBytes : ['$field', 'string']
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }, {
        $limit : 5
    }
]);
kz_sergey
la source
agréable! existe-t-il un moyen de faire correspondre tout le document? ou faire le cadre d'agrégation faire une requête de suivi pour ce faire? En ce moment, un match ressemble à:{ "_id" : ObjectId("5aba5ad988385120a01b1ac2"), "fieldExists" : 4 }
Gianfranco P.
dans l'étape du projet $
projetez
4

String 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
la source
2

J'ai trouvé un outil gratuit pour traduire les requêtes MYSQL en MongoDB. http://www.querymongo.com/ J'ai vérifié avec plusieurs requêtes. comme je vois presque tous sont corrects. Selon cela, la réponse est

db.users.find({
    "name": "%m%"
});
Lakmal Vithanage
la source
2

MongoRegex est obsolète.
Utilisez MongoDB \ BSON \ Regex

$regex = new MongoDB\BSON\Regex ( '^m');
$cursor = $collection->find(array('users' => $regex));
//iterate through the cursor
Albert s
la source
Il est important de noter que cela fait référence à la classe MongoRegex en PHP . Pas très pertinent pour cette question qui concerne Node. Cela devrait probablement être un commentaire ou mieux encore - une question à réponse automatique dans un article séparé.
Boaz - Reinstate Monica
2
db.customer.find({"customerid": {"$regex": "CU_00000*", "$options": "i"}}).pretty()

Lorsque nous recherchons des modèles de chaîne, il est toujours préférable d'utiliser le modèle ci-dessus comme lorsque nous ne sommes pas sûrs de la casse. J'espère que cela pourra aider!!!

priya raj
la source