sql >> Databasteknik >  >> NoSQL >> MongoDB

Hur man använder en SQL LIKE-sats i MongoDB

För den här handledningen kommer vi att använda den official dummy dataset , som innehåller många restaurangdokument från hela New York-området.

Här är ett exempel på den grundläggande dokumentstrukturen i denna samling, med hjälp av .findOne() metod:

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

Faktens kraft

Den viktigaste pusselbiten när du söker inom en MongoDB-samling är den enkla men flexibla db.collection.find() metod.

Med .find() , kan du enkelt fråga en samling dokument genom att skicka några enkla parametrar och returnera en cursor . En cursor är helt enkelt en resultatuppsättning och kan itereras igenom för att manipulera eller på annat sätt använda dokumenten som pekas på av cursor .

Som ett enkelt exempel på .find() metod kommer vi att försöka hitta alla restauranger i vår samling som servern Hamburgers som deras 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" }
...

Resultatuppsättningen är ganska stor, så ett bättre mått för våra testexempel skulle vara att kedja .count() metod till .find() för att helt enkelt se hur många dokument som matchade vår fråga:

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

Det är många hamburgare!

Söka efter ordlikheter med regex

Nu när vi använder .find() för att fråga efter vår samling kan vi faktiskt ändra vår syntax lite och börja söka efter matchningar baserat på ett ord eller en fras som kan vara en delvis matcha inom ett givet fält, liknande LIKE operatör för SQL-motorer.

Tricket är att använda regular expressions (eller regex för kort), vilket i grunden är en textsträng som definierar ett sökmönster. Det finns ett antal regex motorer som är skrivna i lite olika syntax, men grunderna är i princip desamma, och i det här fallet använder MongoDB Perl Regex (PCRE) motor.

På den mest grundläggande nivån, ett regex uttryck är en sträng (serie av tecken) omgiven på båda sidor av ett enda snedstreck (/ ).

Till exempel, om vi vill använda regex för att utföra samma fråga som ovan och ta reda på hur många restauranger som serverar Hamburgers , vi kan ersätta vår sträng "Hamburgers" med /Hamburgers/ istället:

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

Nyfikna observatörer kanske inser att vi i praktiken inte har ändrat någonting i själva frågan vi utför – vi letar fortfarande helt enkelt upp alla dokument där cuisine fältet är lika med strängen "Hamburgers" .

Som sagt, genom att helt enkelt använda regex istället för en vanlig "citerad sträng" kan vi börja leta efter partiella ord/frasmatchningar istället.

Låt oss till exempel titta på borough för att få en bättre uppfattning om hur detta fungerar. Först kommer vi att märka att det finns sex stadsdelar totalt inom vår samling:

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

Låt oss nu använda regex för att ta reda på hur många restauranger som finns i Bronx stadsdel:

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

Men tänk dig att vi vill hitta antalet restauranger där borough börjar med de tre första tecknen "Bro" . Vi skulle ändra vårt regex väldigt lite, som så:

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

Vi ser över 6 000 ytterligare dokument i denna resultatuppsättning, vilket är vettigt eftersom vi inte bara får resultat där borough är är "Bronx" , men också allt för "Brooklyn" likaså.

Caret-tecknet (^ ) anger platsen i vår sträng som ska vara början , så om vi hade ett dokument där de tre bokstäverna stod mitt i fältet, skulle vi inte få en matchning.

Som ett annat snabbt exempel, låt oss söka var som helst i fältet för tecknen "at" , vilket borde ge oss resultat för både "Manhattan" och "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

Visst har vår sista fråga kombinerat de två resultatuppsättningarna till en.

Du kanske märker att även om våra tecken "AT" är versaler i vårt regex sträng, men de är gemener i de faktiska dokumentposterna returnerade vi fortfarande resultat. Detta beror på att vi också har lagt till den speciella i flagga efter vårt regex avslutande snedstreck (/ ). Detta informerar regex motor som vi vill att sökningen ska vara case insensitive , matchande oavsett versaler eller gemener.


  1. mongodb-tjänsten startar inte

  2. Meteormetod kontra neka/tillåt regler

  3. DB med bästa inserts/sek prestanda?

  4. node.js mongodb välj dokument med _id node-mongodb-native