MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

So verwenden Sie eine SQL LIKE-Anweisung in MongoDB

Für dieses Tutorial verwenden wir den official dummy dataset , das zahlreiche Restaurantdokumente aus der Umgebung von New York enthält.

Hier ist ein Beispiel für die grundlegende Dokumentstruktur in dieser Sammlung unter Verwendung von .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"
}

Die Kraft des Findens

Das wichtigste Puzzleteil bei der Suche innerhalb einer MongoDB-Sammlung ist das einfache, aber flexible db.collection.find() Methode.

Mit .find() können Sie ganz einfach eine Sammlung von Dokumenten abfragen, indem Sie ein paar einfache Parameter übergeben und einen cursor zurückgeben . Ein cursor ist einfach eine Ergebnismenge und kann durchlaufen werden, um die Dokumente, auf die der cursor zeigt, zu manipulieren oder anderweitig zu nutzen .

Als einfaches Beispiel für .find() In Aktion versuchen wir, alle Restaurants in unserer Sammlung zu finden, die Hamburgers servieren als ihre 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" }
...

Die Ergebnismenge ist ziemlich groß, daher wäre eine bessere Messung für unsere Testbeispiele die Verkettung von .count() Methode auf .find() um einfach zu sehen, wie viele Dokumente mit unserer Suchanfrage übereinstimmen:

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

Das sind viele Burger!

Suche nach Wortähnlichkeiten mit Regex

Jetzt verwenden wir .find() Um unsere Sammlung abzufragen, können wir unsere Syntax tatsächlich geringfügig ändern und mit der Suche nach Übereinstimmungen basierend auf einem Wort oder einer Phrase beginnen, die ein Teil sein kann Übereinstimmung innerhalb eines bestimmten Feldes, ähnlich dem LIKE Operator für SQL-Engines.

Der Trick besteht darin, regular expressions zu verwenden (oder regex kurz), die im Grunde eine Textzeichenfolge ist, die ein Suchmuster definiert. Es gibt eine Reihe von regex Engines, die in leicht unterschiedlicher Syntax geschrieben sind, aber die Grundlagen sind im Grunde alle gleich, und in diesem Fall verwendet MongoDB den Perl Regex (PCRE) Motor.

Auf der einfachsten Ebene ein regex Ausdruck ist eine Zeichenfolge (Zeichenfolge), die auf beiden Seiten von einem einzelnen Schrägstrich (/) umschlossen ist ).

Zum Beispiel, wenn wir regex verwenden wollen , um dieselbe Abfrage wie oben durchzuführen und herauszufinden, wie viele Restaurants Hamburgers anbieten , können wir unseren String "Hamburgers" ersetzen mit /Hamburgers/ stattdessen:

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

Aufmerksame Beobachter werden vielleicht erkennen, dass wir praktisch nichts an der eigentlichen Abfrage geändert haben, die wir durchführen – wir suchen immer noch einfach alle Dokumente nach cuisine Feld ist gleich die Zeichenfolge "Hamburgers" .

Das heißt, indem Sie einfach regex verwenden Anstelle einer normalen Zeichenfolge in Anführungszeichen können wir damit beginnen, nach Teilübereinstimmungen von Wörtern/Phrasen zu suchen stattdessen.

Schauen wir uns zum Beispiel den borough an Feld, um eine bessere Vorstellung davon zu bekommen, wie das funktioniert. Zuerst werden wir feststellen, dass es in unserer Sammlung insgesamt sechs Bezirke gibt:

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

Lassen Sie uns nun regex verwenden um herauszufinden, wie viele Restaurants es in der Bronx gibt Stadtteil:

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

Aber stellen Sie sich vor, wir möchten die Anzahl der Restaurants in borough finden beginnt mit die ersten drei Zeichen "Bro" . Wir würden unseren regex ändern ganz leicht, etwa so:

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

Wir sehen über 6000 zusätzliche Dokumente in dieser Ergebnismenge, was sinnvoll ist, weil wir nicht nur Ergebnisse dort erhalten, wo der borough ist ist "Bronx" , sondern auch alles für "Brooklyn" auch.

Das Caret-Zeichen (^ ) gibt die Stelle in unserem String an, die der Anfang sein soll , wenn wir also ein Dokument hätten, in dem diese drei Buchstaben in der Mitte des Felds stehen, würden wir keine Übereinstimmung erhalten.

Lassen Sie uns als weiteres kurzes Beispiel irgendwo suchen in das Feld für die Zeichen "at" , was uns Ergebnisse für "Manhattan" liefern sollte und "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

Tatsächlich hat unsere letzte Abfrage die beiden Ergebnismengen zu einer kombiniert.

Sie werden das vielleicht bemerken, obwohl unsere Zeichen "AT" werden in unserem regex in Großbuchstaben geschrieben Zeichenfolge, aber sie sind Kleinbuchstaben in den eigentlichen Dokumentdatensätzen haben wir immer noch Ergebnisse zurückgegeben. Das liegt daran, dass wir auch das spezielle i hinzugefügt haben Flag nach unserem abschließenden Regex-Schrägstrich (/ ). Dies informiert den regex Suchmaschine, die case insensitive soll , Übereinstimmung unabhängig von Groß- oder Kleinschreibung.