Cvičenie 4 - Práca s dokumentovou databázou MongoDB

Cieľom štvrtého cvičenia je naučiť sa základom práce s dokumentovou databázou MongoDB.

Inštalácia MongoDB

Pri inštalácii na spoločný server postupujte spolu v dvojiciach.

  1. 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
  2. Nainštalujte databázový server a nástroje pre klienta príkazmi:

    sudo yum install -y mongodb-org
  3. Spustite službu databázového servera:

    sudo service mongod start

Import dát

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

Práca s klientom mongo

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.

Dopytovanie

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()

Agregácie

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

Úlohy riešte samostatne.

Úloha 4.1

Spočítajte, koľko je Talianskych reštaurácií na Manhattane s hodnotením B.

Úloha 4.2

Usporiadajte Brazílske reštaurácie v Queens podľa smerovacieho čísla zostupne a podľa názvu vzostupne.

Úloha 4.3

Prečítajte si dokumentáciu k agregačnému príkazu $unwind. Spočítajte celkové skóre pre všetky reštaurácie.

Úloha 4.4

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.

Úloha 4.5

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.

Úloha 4.6

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 ].