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 .


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


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


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

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

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


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.


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!


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

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


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

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

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

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)

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


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



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.


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

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é


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

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]

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" }

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

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


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

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


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%"
});

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

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!!!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.