V tomto tutoriálu budeme používat official dummy dataset , která obsahuje četné dokumenty o restauracích z celé oblasti New Yorku.
Zde je příklad základní struktury dokumentu v této kolekci pomocí .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"
}
Síla hledání
Nejdůležitějším kouskem skládačky při vyhledávání v kolekci MongoDB je jednoduchý, ale flexibilní db.collection.find() metoda.
Pomocí .find() , můžete se snadno dotazovat na kolekci dokumentů předáním několika jednoduchých parametrů a vrátit cursor . cursor je prostě sada výsledků a lze ji iterovat za účelem manipulace nebo jiného využití dokumentů, na které ukazuje cursor .
Jako jednoduchý příklad .find() metoda v akci, pokusíme se najít všechny restaurace v naší kolekci, které server Hamburgers jako jejich 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" }
...
Sada výsledků je poměrně velká, takže lepším měřením pro naše testovací příklady by bylo řetězení .count() metoda na .find() abyste jednoduše viděli, kolik dokumentů odpovídalo našemu dotazu:
> db.restaurants.find( { cuisine: "Hamburgers" } ).count()
433
To je spousta hamburgerů!
Hledání podobností slov pomocí regulárního výrazu
Nyní, když používáme .find() k dotazu na naši sbírku můžeme skutečně nepatrně upravit svou syntaxi a začít hledat shody na základě slova nebo fráze, které mohou být částečné shodu v daném poli, podobně jako LIKE operátor pro SQL motory.
Trik je v použití regular expressions (nebo regex zkráceně), což je v podstatě textový řetězec, který definuje vzor vyhledávání. Existuje několik regular expressions enginy, které jsou napsány v mírně odlišné syntaxi, ale základy jsou v zásadě stejné, a v tomto případě MongoDB používá Perl Regex (PCRE) motor.
Na nejzákladnější úrovni regex výraz je řetězec (řada znaků) uzavřený na obou stranách jedním lomítkem (/ ).
Například pokud chceme použít regex provést stejný dotaz jako výše a zjistit, kolik restaurací podává Hamburgers , můžeme nahradit náš řetězec "Hamburgers" pomocí /Hamburgers/ místo toho:
> db.restaurants.find( { cuisine: /Hamburgers/ } ).count()
433
Zapálení pozorovatelé mohou rozpoznat, že jsme na skutečném dotazu, který provádíme, prakticky nic nezměnili – stále jednoduše vyhledáváme všechny dokumenty, kde je cuisine pole se rovná řetězec "Hamburgers" .
To znamená jednoduše pomocí regex místo normálního „řetězce v uvozovkách“ můžeme začít hledat částečné shody slov/frází místo toho.
Podívejme se například na borough pole, abyste získali lepší představu o tom, jak to funguje. Nejprve si všimneme, že v naší kolekci je celkem šest městských částí:
> db.restaurants.distinct('borough')
[
"Brooklyn",
"Bronx",
"Manhattan",
"Queens",
"Staten Island",
"Missing"
]
Nyní použijeme regex zjistit, kolik restaurací je v Bronx čtvrť:
> db.restaurants.find( { borough: /Bronx/ } ).count()
2338
Ale představte si, že chceme najít počet restaurací, kde je borough začíná na první tři znaky "Bro" . Upravili bychom náš regex velmi mírně, asi takto:
> db.restaurants.find( { borough: /^Bro/ } ).count()
8424
V této sadě výsledků vidíme více než 6 000 dalších dokumentů, což dává smysl, protože nejenže dostáváme výsledky tam, kde borough je "Bronx" , ale také vše pro "Brooklyn" také.
Znak stříšky (^ ) určuje umístění v našem řetězci, které by mělo být začátkem , takže pokud bychom měli dokument, kde by tato tři písmena byla uprostřed pole, nedostali bychom shodu.
Jako další rychlý příklad, pojďme hledat kdekoli v poli pro znaky "at" , což by nám mělo poskytnout výsledky pro oba "Manhattan" a "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
Náš poslední dotaz samozřejmě spojil tyto dvě sady výsledků do jedné.
Můžete si všimnout, že i když naše znaky "AT" jsou v našem regex velká písmena řetězec, ale jsou malá ve skutečných záznamech dokumentů jsme stále vraceli výsledky. Je to proto, že jsme přidali také speciální i příznak za naším uzavíracím lomítkem regulárního výrazu (/ ). To informuje regex vyhledávač, u kterého chceme, aby vyhledávání case insensitive , odpovídající bez ohledu na velká nebo malá písmena.