sql >> Database teknologi >  >> NoSQL >> MongoDB

Sådan bruger du en SQL LIKE-sætning i MongoDB

Til denne øvelse bruger vi det official dummy dataset , som indeholder talrige restaurantdokumenter fra hele New York-området.

Her er et eksempel på den grundlæggende dokumentstruktur i denne samling ved hjælp af .findOne() metode:

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

Kraften ved at finde

Den vigtigste brik i puslespillet, når du søger i en MongoDB-samling, er den enkle, men fleksible db.collection.find() metode.

Med .find() , kan du nemt forespørge en samling af dokumenter ved at sende nogle få simple parametre og returnere en cursor . En cursor er simpelthen et resultatsæt og kan gentages for at manipulere eller på anden måde gøre brug af de dokumenter, der peges på af cursor .

Som et simpelt eksempel på .find() metode i aktion, vil vi forsøge at finde alle restauranter i vores samling, der serverer Hamburgers som deres 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" }
...

Resultatsættet er ret stort, så en bedre måling for vores testeksempler ville være at sammenkæde .count() metode til .find() for blot at se, hvor mange dokumenter der matchede vores forespørgsel:

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

Det er mange burgere!

Søgning efter ord-ligheder ved hjælp af regulært udtryk

Nu hvor vi bruger .find() for at forespørge på vores samling kan vi faktisk ændre vores syntaks en smule og begynde at søge efter match baseret på et ord eller en sætning, der kan være en delvis match inden for et givet felt, svarende til LIKE operatør til SQL-motorer.

Tricket er at bruge regular expressions (eller regex for kort), som dybest set er en tekststreng, der definerer et søgemønster. Der er en række regex motorer, der er skrevet i lidt forskellig syntaks, men de grundlæggende principper er alle grundlæggende de samme, og i dette tilfælde bruger MongoDB Perl Regex (PCRE) motor.

På det mest grundlæggende niveau, et regex udtryk er en streng (serie af tegn) omgivet på begge sider af en enkelt skråstreg (/ ).

For eksempel, hvis vi vil bruge regex for at udføre den samme forespørgsel som ovenfor og finde ud af, hvor mange restauranter der serverer Hamburgers , kan vi erstatte vores streng "Hamburgers" med /Hamburgers/ i stedet:

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

Spændte iagttagere vil måske erkende, at vi i virkeligheden ikke har ændret noget ved den faktiske forespørgsel, vi udfører – vi søger stadig blot alle dokumenter, hvor cuisine felt er lig med strengen "Hamburgers" .

Når det er sagt, ved blot at bruge regex i stedet for en normal "anført streng", kan vi begynde at lede efter delvise ord/sætningsmatches i stedet.

Lad os for eksempel se på borough felt for at få en bedre ide om, hvordan dette fungerer. Først vil vi bemærke, at der er seks bydele i alt inden for vores samling:

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

Lad os nu bruge regex for at finde ud af, hvor mange restauranter der er i Bronx bydel:

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

Men forestil dig, at vi ønsker at finde antallet af restauranter, hvor borough starter med de første tre tegn "Bro" . Vi ville ændre vores regex meget lidt, sådan:

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

Vi ser over 6000 yderligere dokumenter i dette resultatsæt, hvilket giver mening, fordi vi ikke kun får resultater, hvor borough er er "Bronx" , men også alt til "Brooklyn" også.

Caret-tegnet (^ ) angiver placeringen i vores streng, som skal være begyndelsen , så hvis vi havde et dokument, hvor de tre bogstaver var i midten af ​​feltet, ville vi ikke få et match.

Som et andet hurtigt eksempel, lad os søge hvor som helst i feltet for tegnene "at" , hvilket skulle give os resultater for både "Manhattan" og "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

Sikkert nok har vores sidste forespørgsel kombineret de to resultatsæt til ét.

Du bemærker måske, at selvom vores tegn "AT" er store bogstaver i vores regex streng, men de er små bogstaver i de faktiske dokumentposter returnerede vi stadig resultater. Dette skyldes, at vi også tilføjede den særlige i flag efter vores regex afsluttende skråstreg (/ ). Dette informerer regex motor, som vi ønsker, at søgningen skal være case insensitive , matchende uanset store eller små bogstaver.


  1. Sortering efter maksimalt matrixfelt, stigende eller faldende

  2. Redis cache vs brug af hukommelse direkte

  3. Skinner, Sidekiq - Redis NOAUTH

  4. Operationel databasesikkerhed – del 1