W tym samouczku użyjemy official dummy dataset
, który zawiera liczne dokumenty dotyczące restauracji z całego obszaru Nowego Jorku.
Oto przykład podstawowej struktury dokumentu w tej kolekcji, przy użyciu .findOne()
metoda:
> 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"
}
Moc znajdowania
Najważniejszym elementem układanki podczas wyszukiwania w kolekcji MongoDB jest prosta, ale elastyczna db.collection.find()
metoda.
Z .find()
, możesz łatwo przeszukiwać kolekcję dokumentów, przekazując kilka prostych parametrów i zwracając cursor
. cursor
jest po prostu zestawem wyników i może być iterowany w celu manipulowania lub innego wykorzystania dokumentów wskazywanych przez cursor
.
Jako prosty przykład .find()
w działaniu, spróbujemy znaleźć wszystkie restauracje w naszej kolekcji, które obsługują Hamburgers
jako ich 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" }
...
Zestaw wyników jest dość duży, więc lepszym pomiarem dla naszych przykładów testowych byłoby łańcuchowe .count()
metodę na .find()
aby po prostu zobaczyć, ile dokumentów pasuje do naszego zapytania:
> db.restaurants.find( { cuisine: "Hamburgers" } ).count()
433
To dużo hamburgerów!
Wyszukiwanie podobieństw do słów przy użyciu wyrażenia regularnego
Teraz, gdy używamy .find()
aby wysłać zapytanie do naszej kolekcji, możemy nieznacznie zmodyfikować naszą składnię i rozpocząć wyszukiwanie dopasowań w oparciu o słowo lub frazę, która może być częściową pasuje w obrębie danego pola, podobnie jak w LIKE
operator dla silników SQL.
Sztuką jest wykorzystanie regular expressions
(lub regex
w skrócie), który jest zasadniczo ciągiem tekstowym, który definiuje wzorzec wyszukiwania. Istnieje wiele regex
silniki, które są napisane w nieco innej składni, ale podstawy są zasadniczo takie same, w tym przypadku MongoDB używa Perl Regex (PCRE)
silnik.
Na najbardziej podstawowym poziomie regex
wyrażenie to ciąg (seria znaków) ujęty z obu stron pojedynczym ukośnikiem (/
).
Na przykład, jeśli chcemy użyć regex
aby wykonać to samo zapytanie co powyżej i dowiedzieć się, ile restauracji serwuje Hamburgers
, możemy zastąpić nasz ciąg "Hamburgers"
z /Hamburgers/
zamiast tego:
> db.restaurants.find( { cuisine: /Hamburgers/ } ).count()
433
Wnikliwi obserwatorzy mogą rozpoznać, że skutecznie nie zmieniliśmy niczego w wykonywanym przez nas zapytaniu – nadal po prostu wyszukujemy wszystkie dokumenty, w których znajduje się cuisine
pole jest równe ciąg "Hamburgers"
.
To powiedziawszy, po prostu używając regex
zamiast normalnego „ciągu w cudzysłowie”, możemy zacząć szukać częściowych dopasowań słów/fraz zamiast tego.
Na przykład spójrzmy na borough
pole, aby lepiej zrozumieć, jak to działa. Najpierw zauważymy, że w naszej kolekcji jest w sumie sześć gmin:
> db.restaurants.distinct('borough')
[
"Brooklyn",
"Bronx",
"Manhattan",
"Queens",
"Staten Island",
"Missing"
]
Teraz użyjmy regex
aby dowiedzieć się, ile restauracji znajduje się w Bronx
gmina:
> db.restaurants.find( { borough: /Bronx/ } ).count()
2338
Ale wyobraź sobie, że chcemy znaleźć liczbę restauracji, w których borough
zaczyna się od pierwsze trzy znaki "Bro"
. Zmodyfikujemy nasze regex
bardzo nieznacznie, jak tak:
> db.restaurants.find( { borough: /^Bro/ } ).count()
8424
W tym zestawie wyników widzimy ponad 6000 dodatkowych dokumentów, co ma sens, ponieważ nie tylko otrzymujemy wyniki, w których borough
to "Bronx"
, ale także wszystko dla "Brooklyn"
również.
Znak karetki (^
) określa lokalizację w naszym ciągu, która powinna być początkiem , więc gdybyśmy mieli dokument, w którym te trzy litery były na środku pola, nie dostalibyśmy dopasowania.
Jako kolejny szybki przykład wyszukajmy wszędzie w polu na znaki "at"
, co powinno dać nam wyniki dla obu "Manhattan"
i "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
Rzeczywiście, nasze ostatnie zapytanie połączyło dwa zestawy wyników w jeden.
Możesz zauważyć, że chociaż nasze postacie "AT"
są wielkimi literami w naszym regex
ciąg znaków, ale są małe w rzeczywistych zapisach dokumentów nadal zwracaliśmy wyniki. Dzieje się tak, ponieważ dodaliśmy również specjalne i
flaga po naszym ukośniku zamykającym wyrażenie regularne (/
). To informuje regex
silnik, który chcemy, aby wyszukiwanie case insensitive
, pasujące niezależnie od wielkich lub małych liter.