Cieľom štvrtého cvičenia je naučiť sa základom práce s dokumentovou databázou MongoDB.
Pri inštalácii na spoločný server postupujte spolu v dvojiciach.
V adresári /etc/yum.repos.d/ vytvorte ako administrátor súbor MongoDB-3.2.repo s nasledujúcim obsahom:
[mongodb-org-3.2] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.2/x86_64/ gpgcheck=0 enabled=1
Nainštalujte databázový server a nástroje pre klienta príkazmi:
sudo yum install -y mongodb-org
Spustite službu databázového servera:
sudo service mongod start
Pri importe dát postupujte spolu v dvojiciach.
Na cvičení budete pracovať s dátami, ktoré popisujú hodnotenie reštaurácií vo formáte JSON. Jeden záznam bude vyzerať takto:
Najprv si stiahnite súbor s testovacími dátami do svojho domovského adresára.
cd wget http://people.tuke.sk/martin.sarnovsky/tsvd/files/restaurants.json
Dáta sú v MongoDB uložené v databázach, ktoré sú rozdelené na kolekcie. Načítajte si dáta do databázy tsvd a kolekcie restaurants.
mongoimport --db tsvd --collection restaurants --drop --file restaurants.json
K databáze sa pripojíte s príkazom mongo
. Po pripojení sa vám zobrazí príkazový riadok, v ktorom môžete zadávať príkazy pre dopytovanie, pridávanie, modifikovanie alebo mazanie dát.
Program mongo
ukončíte príkazom quit()
.
Pomocou príkazu show databases
sa zobrazí zoznam existujúcich databáz. Príkazom use [databáza]
vyberiete databázu, s ktorou chcete pracovať.
Nasledujúcimi príkazmi môžete zobraziť kolekcie v databáze tsvd a počet objektov v kolekcii restaurants.
use tsvd show collections db.restaurants.count()
Môžete sa vrátiť k predchádzajúcim príkazom pomocou klávesy šípka hore / šípka dole. Pomoc získate príkazom help
.
Základné typy dopytov sa vykonávajú pomocou príkazu db.[kolekcia].find([dopyt])
.
Nasledujúci príkaz zobrazí reštaurácie v štvrti Manhattan:
db.restaurants.find( { "borough": "Manhattan" } )
V dopytoch sa môžete odkazovať aj na vnorené objekty, napr. na smerovacie číslo vnorené v objekte adresy:
db.restaurants.find( { "address.zipcode": "10075" } )
Odkazovanie cez .
je možné použiť aj keď sú vnorené objekty v poli:
db.restaurants.find( { "grades.grade": "B" } )
Okrem vyhľadávania podľa hodnôt môžete použiť porovnávanie pomocou príkazov menší $lt
alebo väčší $gt
. Nasledujúci dopyt vráti reštaurácie s hodnotením viac než 30:
db.restaurants.find( { "grades.score": { $gt: 30 } } )
Zložitejšie dopyty sa vytvárajú zadaním viacerých vlastností v objekte dopytu (logická spojka a). Napr. nasledujúci dopyt vráti Talianske reštaurácie so smerovacím číslom 10075:
db.restaurants.find( { "cuisine": "Italian", "address.zipcode": "10075" } )
Logická podmienka alebo sa zapisuje samostatným príkazom $or
, nasledujúci príklad vráti reštaurácie ktoré ponúkajú talianske jedlá, alebo majú smerovacie číslo 10075:
db.restaurants.find( { $or: [ { "cuisine": "Italian" }, { "address.zipcode": "10075" } ] })
Výsledky je možné usporiadať príkazom sort
. Nasledujúci príkaz zoradí všetky objekty najprv podľa štvrti vzostupne a potom podľa čísla zostupne:
db.restaurants.find().sort( { "borough": 1, "address.zipcode": -1 } )
Ak chcete len zistiť počet objektov zahrnutých do výsledku dopytu použite príkaz count
.
db.restaurants.find( { "grades.score": { $gt: 30 } } ).count()
Pomocou agregácií môžeme vytvoriť zložité dopyty, ktoré dáta filtrujú a zoskupujú podľa zadaných kritérií.
Pri agregáciách je dopyt rozdelený na postupnosť základných operácií, ktoré sú potom aplikované postupne na objekty v kolekcii.
Pri spracovaní môžu byť dáta filtrované (príkaz $match
), transformované (príkaz $project
), usporiadané (príkaz $sort
) a agregované (príkaz $group
).
Základný formát príkazu pre agregovanie dát je db.[kolekcia].aggregate( [ [príkaz1], [príkaz2], [...] ] )
.
Napr. nasledujúci príkaz najprv odfiltruje iba tie objekty z kolekcie, ktoré sú vo štvrti Queens a varia Brazílsku kuchyňu, potom ich zoskupí podľa smerovacieho čísla, a nakoniec vypočíta koľko je reštaurácií pre každé smerovacie číslo (príkaz musí byť zapísaný v jednom riadku):
db.restaurants.aggregate([ { $match: { "borough": "Queens", "cuisine": "Brazilian" } }, { $group: { "_id": "$address.zipcode" , "count": { $sum: 1 } } } ])
V príkaze $group
môžete namiesto jednoduchého počtu objektov v skupine určiť ďalšie agregačné funkcie ako napr. priemer $avg
(v príklade je uvedená len časť dopytu s príkazom $group
):
{ $group: { "_id": "$address.zipcode" , "avg_grade": { $avg: "$grades.score" } } }
Ak chcete spočítať agregačnú funkciu pre všetky záznamy bez zoskupenia, ako _id
môžete zadať null
. Viac informácií o agregáciách nájdete na tejto stránke (v angličtine).
Úlohy riešte samostatne.
Spočítajte, koľko je Talianskych reštaurácií na Manhattane s hodnotením B.
Usporiadajte Brazílske reštaurácie v Queens podľa smerovacieho čísla zostupne a podľa názvu vzostupne.
Prečítajte si dokumentáciu k agregačnému príkazu $unwind
. Spočítajte celkové skóre pre všetky reštaurácie.
Prečítajte si dokumentáciu k agregačnému príkazu $unwind
. Spočítajte celkové skóre pre reštaurácie v Queens a zoskupte ich podľa hodnotenia grade.
Prečítajte si dokumentáciu k agregačnému príkazu $unwind
. Spočítajte celkové skóre pre reštaurácie v Queens, zoskupte ich podľa smerovacieho čísla a vráťte 10 smerovacích čísel s najväčším skóre.
Vytvorte si geografický index pre vlastnosť address.coord príkazom db.restaurants.createIndex("address.coord":"2dsphere")
.
Prečítajte si dokumentáciu k príkazu $geoNear
.
Vráťte 10 najbližších reštaurácií v okolí geografickej polohy [ -73.856077, 40.848447 ].