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.