sql >> Database >  >> NoSQL >> MongoDB

Een SQL LIKE-instructie gebruiken in MongoDB

Voor deze tutorial gebruiken we de official dummy dataset , die tal van restaurantdocumenten bevat uit de omgeving van New York.

Hier is een voorbeeld van de basisdocumentstructuur in deze verzameling, met behulp van de .findOne() methode:

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

De kracht van vinden

Het belangrijkste puzzelstukje bij het zoeken binnen een MongoDB-verzameling is de eenvoudige maar flexibele db.collection.find() methode.

Met .find() , kunt u eenvoudig een verzameling documenten opvragen door een paar eenvoudige parameters door te geven en een cursor terug te sturen . Een cursor is gewoon een resultaatset en kan worden herhaald om de documenten te manipuleren of anderszins te gebruiken waarnaar wordt verwezen door de cursor .

Als een eenvoudig voorbeeld van de .find() methode in actie, we zullen proberen alle restaurants in onze collectie te vinden die server Hamburgers als hun 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" }
...

De resultatenset is vrij groot, dus een betere maatstaf voor onze testvoorbeelden zou zijn om de .count() te koppelen methode naar .find() om eenvoudig te zien hoeveel documenten overeenkwamen met onze zoekopdracht:

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

Dat zijn veel hamburgers!

Zoeken naar woordovereenkomsten met Regex

Nu we .find() gebruiken om onze verzameling te doorzoeken, kunnen we onze syntaxis zelfs maar een klein beetje aanpassen en beginnen met zoeken naar overeenkomsten op basis van een woord of zin die een gedeeltelijk kan zijn match binnen een bepaald veld, vergelijkbaar met de LIKE operator voor SQL-engines.

De truc is om regular expressions te gebruiken (of regex in het kort), wat in feite een tekenreeks is die een zoekpatroon definieert. Er zijn een aantal regex engines die in een iets andere syntaxis zijn geschreven, maar de grondbeginselen zijn in principe allemaal hetzelfde, en in dit geval gebruikt MongoDB de Perl Regex (PCRE) motor.

Op het meest basale niveau, een regex uitdrukking is een tekenreeks (reeks tekens) die aan beide zijden is ingesloten door een enkele schuine streep (/ ).

Als we bijvoorbeeld regex . willen gebruiken om dezelfde zoekopdracht als hierboven uit te voeren en erachter te komen hoeveel restaurants Hamburgers serveren , kunnen we onze string "Hamburgers" vervangen met /Hamburgers/ in plaats daarvan:

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

Scherpe waarnemers zullen misschien herkennen dat we feitelijk niets hebben veranderd aan de eigenlijke zoekopdracht die we uitvoeren - we zoeken nog steeds gewoon alle documenten op waar de cuisine veld is gelijk aan de string "Hamburgers" .

Dat gezegd hebbende, door simpelweg regex . te gebruiken in plaats van een normale "tekenreeks tussen aanhalingstekens", kunnen we beginnen te zoeken naar gedeeltelijke woord/zin-overeenkomsten in plaats daarvan.

Laten we bijvoorbeeld eens kijken naar de borough veld om een ​​beter idee te krijgen van hoe dit werkt. Eerst zullen we zien dat er in totaal zes stadsdelen in onze collectie zijn:

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

Laten we nu regex gebruiken om erachter te komen hoeveel restaurants er in de Bronx zijn gemeente:

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

Maar stel je voor dat we het aantal restaurants willen vinden waar borough begint met de eerste drie tekens "Bro" . We zouden onze regex . aanpassen heel lichtjes, zoals zo:

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

We zien meer dan 6000 extra documenten in deze resultatenset, wat logisch is omdat we niet alleen resultaten krijgen waar de borough is "Bronx" , maar ook alles voor "Brooklyn" ook.

Het caret-teken (^ ) specificeert de locatie in onze string die het begin . zou moeten zijn , dus als we een document hadden waarin die drie letters in het midden van het veld stonden, zouden we geen overeenkomst krijgen.

Laten we als een ander snel voorbeeld overal zoeken in het veld voor de karakters "at" , wat ons resultaten zou moeten geven voor zowel "Manhattan" en "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

En ja hoor, onze laatste zoekopdracht heeft de twee resultatensets gecombineerd tot één resultaat.

Je merkt misschien dat, hoewel onze karakters "AT" zijn hoofdletters in onze regex tekenreeks, maar ze zijn kleine letters in de eigenlijke documentrecords hebben we nog steeds resultaten geretourneerd. Dit komt omdat we ook de speciale i . hebben toegevoegd vlag na onze regex afsluitende slash (/ ). Dit informeert de regex engine waarvan we willen dat de zoekopdracht case insensitive is , overeenkomend ongeacht hoofdletters of kleine letters.


  1. Mongoose voegt meerdere objecten toe aan array indien niet gebaseerd op bestaan

  2. Redis binden aan meer dan één IP

  3. MongoDb:Voordeel van het gebruik van ObjectID versus een string met een ID?

  4. Een overzicht van operationele databaserapportage in ClusterControl