MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Comment utiliser une instruction SQL LIKE dans MongoDB

Pour ce tutoriel, nous utiliserons le official dummy dataset , qui contient de nombreux documents sur les restaurants de la région de New York.

Voici un exemple de la structure de base du document dans cette collection, en utilisant le .findOne() méthode :

> db.restaurants.findOne()
{
        "_id" : ObjectId("56c651e7d84ccfde319961af"),
        "address" : {
                "building" : "469",
                "coord" : [
                        -73.961704,
                        40.662942
                ],
                "street" : "Flatbush Avenue",
                "zipcode" : "11225"
        },
        "borough" : "Brooklyn",
        "cuisine" : "Hamburgers",
        "grades" : [
                {
                        "date" : ISODate("2014-12-30T00:00:00Z"),
                        "grade" : "A",
                        "score" : 8
                },
                {
                        "date" : ISODate("2014-07-01T00:00:00Z"),
                        "grade" : "B",
                        "score" : 23
                },
                {
                        "date" : ISODate("2013-04-30T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                },
                {
                        "date" : ISODate("2012-05-08T00:00:00Z"),
                        "grade" : "A",
                        "score" : 12
                }
        ],
        "name" : "Wendy'S",
        "restaurant_id" : "30112340"
}

Le pouvoir de trouver

La pièce la plus importante du puzzle lors de la recherche dans une collection MongoDB est le simple mais flexible db.collection.find() méthode.

Avec .find() , vous pouvez facilement interroger une collection de documents, en passant quelques paramètres simples, et renvoyer un cursor . Un cursor est simplement un ensemble de résultats et peut être itéré pour manipuler ou autrement utiliser les documents pointés par le cursor .

Comme exemple simple du .find() méthode en action, nous essaierons de trouver tous les restaurants de notre collection qui servent Hamburgers comme leur cuisine :

>db.restaurants.find( { cuisine: "Hamburgers" } )
{ "_id" : ObjectId("56c651e7d84ccfde319961af"), "address" : { "building" : "469", "coord" : [ -73.961704, 40.662942 ], "street" : "Flatbush Avenue", "zipcode" : "11225" }, "borough" : "Brooklyn", "cuisine" : "Hamburgers", "grades" : [ { "date" : ISODate("2014-12-30T00:00:00Z"), "grade" : "A", "score" : 8 }, { "date" : ISODate("2014-07-01T00:00:00Z"), "grade" : "B", "score" : 23 }, { "date" : ISODate("2013-04-30T00:00:00Z"), "grade" : "A", "score" : 12 }, { "date" : ISODate("2012-05-08T00:00:00Z"), "grade" : "A", "score" : 12 } ], "name" : "Wendy'S", "restaurant_id" : "30112340" }
...

L'ensemble de résultats est assez volumineux, donc une meilleure mesure pour nos exemples de test serait de chaîner le .count() méthode sur .find() pour voir simplement combien de documents correspondent à notre requête :

> db.restaurants.find( { cuisine: "Hamburgers" } ).count()
433

Ça fait beaucoup de burgers !

Recherche de similarités de mots à l'aide de Regex

Maintenant que nous utilisons .find() pour interroger notre collection, nous pouvons en fait modifier légèrement notre syntaxe et commencer à rechercher des correspondances basées sur un mot ou une phrase qui peut être partielle correspondance dans un champ donné, similaire à LIKE opérateur pour les moteurs SQL.

L'astuce consiste à utiliser des regular expressions (ou regex pour faire court), qui est essentiellement une chaîne de texte qui définit un modèle de recherche. Il existe un certain nombre de regex moteurs qui sont écrits dans une syntaxe légèrement différente, mais les fondamentaux sont tous fondamentalement les mêmes, et dans ce cas, MongoDB utilise le Perl Regex (PCRE) moteur.

Au niveau le plus basique, une regex expression est une chaîne (série de caractères) délimitée des deux côtés par une seule barre oblique (/ ).

Par exemple, si nous voulons utiliser regex pour effectuer la même requête que ci-dessus et savoir combien de restaurants servent des Hamburgers , nous pouvons remplacer notre chaîne "Hamburgers" avec /Hamburgers/ à la place :

> db.restaurants.find( { cuisine: /Hamburgers/ } ).count()
433

Les observateurs attentifs peuvent reconnaître que nous n'avons effectivement rien changé à la requête réelle que nous effectuons - nous recherchons toujours simplement tous les documents où la cuisine le champ est égal à la chaîne "Hamburgers" .

Cela dit, en utilisant simplement regex au lieu d'une "chaîne entre guillemets" normale, nous pouvons commencer à rechercher des correspondances partielles de mot/phrase à la place.

Par exemple, regardons le borough domaine pour avoir une meilleure idée de la façon dont cela fonctionne. Remarquons tout d'abord qu'il y a six arrondissements au total dans notre collection :

> db.restaurants.distinct('borough')
[
        "Brooklyn",
        "Bronx",
        "Manhattan",
        "Queens",
        "Staten Island",
        "Missing"
]

Utilisons maintenant regex pour savoir combien de restaurants il y a dans le Bronx arrondissement :

> db.restaurants.find( { borough: /Bronx/ } ).count()
2338

Mais imaginons que nous voulions trouver le nombre de restaurants où borough commence par les trois premiers caractères "Bro" . Nous modifierions notre regex très légèrement, comme ceci :

> db.restaurants.find( { borough: /^Bro/ } ).count()
8424

Nous voyons plus de 6000 documents supplémentaires dans cet ensemble de résultats, ce qui est logique car non seulement nous obtenons des résultats où le borough est "Bronx" , mais aussi tout pour "Brooklyn" aussi.

Le caractère caret (^ ) spécifie l'emplacement dans notre chaîne qui devrait être le début , donc si nous avions un document où ces trois lettres étaient au milieu du champ, nous n'aurions pas de correspondance.

Comme autre exemple rapide, recherchons n'importe où dans le champ pour les caractères "at" , ce qui devrait nous donner des résultats pour "Manhattan" et "Staten Island" :

> db.restaurants.find( { borough: /Manhattan/ } ).count()
10259

> db.restaurants.find( { borough: /Staten Island/ } ).count()
969

> db.restaurants.find( { borough: /AT/i } ).count()
11228

Effectivement, notre requête finale a combiné les deux ensembles de résultats en un seul.

Vous remarquerez peut-être que même si nos caractères "AT" sont en majuscules dans notre regex chaîne, mais ils sont en minuscules dans les enregistrements de documents réels, nous avons toujours renvoyé des résultats. C'est parce que nous avons également ajouté le spécial i drapeau suivant notre barre oblique fermante regex (/ ). Ceci informe la regex moteur que nous voulons que la recherche soit case insensitive , correspondant indépendamment des majuscules ou des minuscules.