Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Lahko pa si tudi pripravimo JSON datoteko ter vse podatke uvozimo z naslednjim
- ukazom:
- > mongoimport ‐‐db edugeocache ‐‐collection Lokacije ‐‐mode upsert ‐‐upsertFields naziv ‐‐jsonArray ‐‐file ~/workspace/sp‐2017‐2018‐edugeocache/testni_podatki.json
- 2017‐11‐17T12:51:09.932+0000 connected to: localhost
- 2017‐11‐17T12:51:09.940+0000 imported 3 documents
- Ker pri takšnem uvozu podatkov odvisni dokumenti nimajo polja _id , jih je potrebno
- pri komentarjih dodati.
- $ mongo
- > use edugeocache
- > db.Lokacije.find().forEach(function(dokument) {
- for (var i = 0; i < dokument.komentarji.length; i++) {
- dokument.komentarji[i]._id = ObjectId()
- }
- db.Lokacije.update({ "_id" : dokument._id }, dokument)
- })
- 11.1.5 Vključitev podatkovne baze
- 11.1.5.1 Gostovanje MongoDB podatkovne baze na mLab
- Uporabljali bomo ponudnika MongoDB podatkovne baze v oblaku mLab, ki v okviru
- sandbox dostopa omogoča brezplačno uporabo 1 podatkovne baze z do 500 Mb
- podatkov.
- Ko je registracija uspešna in elektronski naslov potrjen, kreiramo novo podatkovno
- bazo tipa sandbox. Podatkovno bazo poimenujemo edugeocache ter dodamo
- uporabnika user z geslom pass ter pridobimo povezavo do podatkovne baze, ki je v
- naslednji obliki:
- mongodb://user:pass@ds113136.mlab.com:13136/edugeocache
- Z naslednjim ukazom lahko iz lokalnega Cloud9 okolja preverimo delovanje naše
- oddaljene MongoDB podatkovne baze, ki jo gostujemo na mLab.
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 23/45
- $ mongo ds113136.mlab.com:13136/edugeocache ‐u user ‐p pass
- MongoDB shell version v3.4.10
- connecting to: mongodb://ds113136.mlab.com:13136/edugeocache
- MongoDB server version: 3.4.9
- Namig: Bodite pozorni na to, da je verzija vašega odjemalca (MongoDB shell)
- novejša od verzije strežnika (MongoDB server), sicer lahko imate težave.
- Nato podatkovno bazo dodamo v parametre Heroku okolja, kar bomo kasneje
- potrebovali v aplikaciji, ko se bomo povezovali na podatkovno bazo
- $ heroku config:set MLAB_URI=mongodb://user:pass@ds113136.mlab.com:13136/edugeocache
- Setting MLAB_URI and restarting ⬢ edugeocache‐sp‐2017‐2018... done, v6
- MLAB_URI: mongodb://user:pass@ds113136.mlab.com:13136/edugeocache
- 11.1.5.2 Prenos podatkov iz lokalne podatkovne baze na mLab
- Ko imamo vzpostavljeno produkcijsko verzijo podatkovne baze na mLab, je potrebno
- vzpostaviti mehanizem za prenos podatkov iz razvojne verzije v produkcijsko verzijo
- podatkovne baze.
- Najprej kreiramo začasno mapo, kamor bomo shranili podatke razvojne verzije
- podatkovne baze.
- $ mkdir ‐p ~/workspace/mongodb/dump
- Potem naredimo posnetek stanja lokalne podatkovne baze v Cloud9 razvojnem
- okolju.
- $ mongodump ‐h localhost:27017 ‐d edugeocache ‐o ~/workspace/mongodb/dump
- 2017‐11‐17T21:11:29.515+0000 writing edugeocache.Lokacije to
- 2017‐11‐17T21:11:29.517+0000 done dumping edugeocache.Lokacije (3 documents)
- Sedaj pa obnovimo vsebino razvojne podatkovne baze na produkcijsko verzijo
- podatkovne baze na mLab.
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 24/45
- $ mongorestore ‐h ds113136.mlab.com:13136 ‐d edugeocache ‐u user ‐p pass ~/workspace/mongodb/dump/edugeocache
- 2017‐11‐17T21:18:15.912+0000 building a list of collections to restore from /home/ubuntu/workspace/mongodb/dump/edugeocache dir
- 2017‐11‐17T21:18:15.931+0000 reading metadata for edugeocache.Lokacije from /home/ubuntu/workspace/mongodb/dump/edugeocache/Lokacije.metadata.json
- 2017‐11‐17T21:18:15.999+0000 restoring edugeocache.Lokacije from /home/ubuntu/workspace/mongodb/dump/edugeocache/Lokacije.bson
- 2017‐11‐17T21:18:16.033+0000 restoring indexes for collection edugeocache.Lokacije from metadata
- 2017‐11‐17T21:18:16.051+0000 finished restoring edugeocache.Lokacije (3 documents)
- 2017‐11‐17T21:18:16.051+0000 done
- Povežimo se na oddaljeno produkcijsko podatkovno bazo na mLab in preverimo, ali so
- podatki na voljo.
- $ mongo ds113136.mlab.com:13136/edugeocache ‐u user ‐p pass
- MongoDB shell version v3.4.10
- connecting to: mongodb://ds113136.mlab.com:13136/edugeocache
- MongoDB server version: 3.4.9
- > show collections
- Lokacije
- system.indexes
- > db.Lokacije.find()
- Če je bil uvoz uspešen, se nam prikažejo vsi podatki, ki smo jih že vnesli v lokalno
- razvojno podatkovno bazo v okolju Cloud9.
- 11.1.5.3 Izbira podatkovne baze glede na razvojno okolje
- V tem trenutku imamo tako vzpostavljeno ločeno razvojno in produkcijsko razvojno
- okolje, ki imata vsaka svojo podatkovno bazo, kot prikazuje slika 11.8.
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 25/45
- Slika 11.8: Razvojno in produkcijsko razvojno okolje, vsako s svojo podatkovno bazo
- Glede na naš cilj ločitve razvojnih okolij, mora naša aplikacija v razvojnem okolju
- uporabljati lokalno podatkovno bazo, v produkcijskem okolju na Heroku pa podatkovno
- bazo, ki gostuje na mLab.
- To bomo dosegli z uporabo spremenljivke NODE_ENV v okolju Node.js.
- Privzeto je Heroku nastavljen na produkcijsko okolje, z naslednjim ukazom pa to še
- eksplicitno zahtevamo.
- $ heroku config:set NODE_ENV=production
- Setting NODE_ENV and restarting ⬢ edugeocache‐sp‐2017‐2018... done, v7
- NODE_ENV: production
- V datoteko db.js dodamo pogoj, kjer preverjamo, ali se aplikacija izvaja v
- produkcijskem okolju. Pri zagonu aplikacije preprosto preverjamo, ali ima okoljska
- spremenljivka NODE_ENV nastavljeno vrednost na production (glej vrstico 4), saj bomo
- takrat uporabili povezovalni niz na produkcijsko podatkovno bazo na mLab, ki je
- opredeljena v okoljski spremenljivki MLAB_URI (glej vrstico 5).
- app_server/models/db.js
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- var mongoose = require('mongoose');
- var dbURI = 'mongodb://localhost/edugeocache';
- + if (process.env.NODE_ENV === 'production') {
- + dbURI = process.env.MLAB_URI;
- + }
- mongoose.connect(dbURI, { useMongoClient: true });
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 26/45
- Uporabniškega imena in gesla za dostop do oddaljene MongoDB podatkovne baze, ki
- jo gostujemo na mLab, ne razkrivamo v izvorni kodi, ampak uporabimo spremenljivko
- MLAB_URI , ki smo jo predhodno nastavili na Heroku okolju.
- 11.1.5.4 Testiranje delovanja
- Če aplikacijo poženemo v razvojnem okolju, vidimo iz izpisov, da smo se povezali z
- lokalno podatkovno bazo.
- $ nodemon
- ...
- Mongoose je povezan na mongodb://localhost/edugeocache
- Sedaj preverimo še povezovanje na produkcijsko podatkovno bazo na mLab, kjer pred
- zagonom aplikacije z nodemon nastavimo okoljski spremenljivki NODE_ENV in
- MLAB_URI .
- $ NODE_ENV=production MLAB_URI=mongodb://user:pass@ds113136.mlab.com:13136/edugeocache nodemon start
- ...
- Mongoose je povezan na mongodb://user:pass@ds113136.mlab.com:13136/edugeocache
- Sedaj še preverimo delovanje v celoti na Heroku produkcijskem okolju.
- $ git add .
- $ git commit ‐m "Dodajanje mLab podatkovne baze"
- $ git push heroku master
- Z ukazom heroku logs lahko preverimo dnevniške zapise na oddaljenem Heroku
- strežniku in poiščemo vrstico, kjer je zapisano, da se je aplikacija povezala s
- produkcijsko podatkovno bazo na mLab.
- $ heroku logs
- ...
- 2017‐11‐17T21:48:52.223480+00:00 app[web.1]: Mongoose je povezan na mongodb://user:pass@ds113136.mlab.com:13136/edugeocache
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 27/45
- 11.2 Priprava REST APIja za dostop do
- MongoDB podatkovne baze
- Do tega trenutka smo vzpostavili MongoDB podatkovno bazo, vendar lahko do nje
- dostopamo zgolj preko ukazne vrstice. V nadaljevanju bomo zgradili REST API (glej
- sliko 11.9), ki nam bo omogočal interakcijo s podatkovno bazo s pomočjo HTTP zahtev
- ter izvajal standardne CRUD operacije.
- Slika 11.9: V nadaljevanju bomo s pomočjo Express, Node.js in Mongoose zgradili
- REST API za dostop do MongoDB podatkovne baze
- 11.2.1 REST API
- REST je bolj arhitekturni stil kot striktno določen protokol. REST je brez stanja, t.j.
- stanja oz. zgodovine trenutnega uporabnika se ne zaveda.
- API omogoča aplikacijam medsebojno komunikacijo.
- Iz tega izhaja, da je REST API vmesnik do aplikacije, brez stanja. V našem primeru
- bomo s pomočjo tega pristopa implementirali dostop do podatkovne baze. Pri
- osnovnem delovanju REST API pričakuje zahtevo, ki se na strani strežnika obdela (po
- potrebi dostopa do podatkovne baze) in vrne odgovor, kot je prikazano na sliki 11.10.
- 129
- 130
- 131
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 28/45
- Slika 11.10: Zaporedje procesiranja pri REST zahtevi
- 11.2.2 URL zahteva
- Kot že omenjeno, želimo z REST APIjem implementirati standardne CRUD operacije:
- dodajanje novega elementa,
- branje seznama več elementov,
- branje določenega elementa,
- posodabljanje določenega elementa,
- brisanje določenega elementa.
- Za obvladovanje podatkov v zvezi z lokacijami bomo potrebovali akcije,
- predstavljene v tabeli 11.1.
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 29/45
- Tabela 11.1: URL naslovi in parametri REST APIja za lokacijo
- Akcija
- URL
- naslov
- Parametri Primer
- Kreiranje
- nove
- lokacije
- /lokacije http://edugeocache.si/api/lokacije
- Branje
- seznama
- lokacij
- /lokacije http://edugeocache.si/api/lokacije
- Branje
- določene
- lokacije
- /lokacije idLokacije http://edugeocache.si/api/lokacije/123
- Posodobitev
- določene
- lokacije
- /lokacije idLokacije http://edugeocache.si/api/lokacije/123
- Brisanje
- določene
- lokacije
- /lokacije idLokacije http://edugeocache.si/api/lokacije/123
- Kot je razvidno iz tabele 11.1 ima vsaka akcija isti URL naslov, medtem ko 3 akcije
- pričakujejo tudi dodatni parameter za določitev točne lokacije.
- 11.2.3 Metoda zahteve
- Če želimo uporabiti isti URL naslov za vse akcije, je za medsebojno razlikovanje
- potrebno uporabiti različne metode zahtev, ki so predstavljene v tabeli 11.2. Pri metodi
- zahteve gre za navodilo strežniku, kakšno akcijo naj izvede.
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 30/45
- Tabela 11.2: Metode zahteve, ki se uporabljajo pri REST API
- Metoda
- zahteve
- Uporaba Odgovor
- POST
- Dodajanje novega dokumenta v
- podatkovno bazo.
- Nov podatkovni objekt v
- podatkovni bazi.
- GET
- Branje obstoječega dokumenta iz
- podatkovne baze.
- Objekt, ki predstavlja odgovor
- na poizvedbo.
- PUT
- Posodabljanje dokumenta v
- podatkovni bazi.
- Posodobljen podatkovni objekt
- iz podatkovne baze.
- DELETE
- Brisanje obstoječega dokumenta
- iz podatkovne baze.
- NULL
- Če sedaj posodobimo tabelo 11.1 s podatki o metodah zahtev, dobimo naslednjo tabelo
- 11.3.
- Tabela 11.3: URL naslovi, parametri in metode REST API za lokacijo
- Akcija Metoda
- URL
- naslov
- Parametri Primer
- Kreiranje
- nove
- lokacije
- POST /lokacije http://edugeocache.si/api/lokacije
- Branje
- seznama
- lokacij
- GET /lokacije http://edugeocache.si/api/lokacije
- Branje
- določene
- lokacije
- GET /lokacije idLokacije http://edugeocache.si/api/lokacije/123
- Posodobitev
- določene
- lokacije
- PUT /lokacije idLokacije http://edugeocache.si/api/lokacije/123
- Brisanje
- določene
- lokacije
- DELETE /lokacije idLokacije http://edugeocache.si/api/lokacije/123
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 31/45
- V tabeli 11.3 imamo osnovne metode, povezane z lokacijami, manjkajo pa nam še
- odvisni dokumenti, v našem primeru so to komentarji, ki so podrobneje opisani v
- tabeli 11.4.
- Tabela 11.4: URL naslovi, parametri in metode REST API za komentarje
- Akcija Metoda URL naslov Parametri Primer
- Kreiranje
- novega
- komentarja
- POST /lokacije/idLokacije/komentarji idLokacije
- http://edugeocache.si/api/
- lokacije/123/komentarji
- Branje
- določenega
- komentarja
- GET /lokacije/idLokacije/komentarji
- idLokacije ,
- idKomentarja
- http://edugeocache.si/api/
- lokacije/123/komentarji/abc
- Posodobitev
- določenega
- komentarja
- PUT /lokacije/idLokacije/komentarji
- idLokacije ,
- idKomentarja
- http://edugeocache.si/api/
- lokacije/123/komentarji/abc
- Brisanje
- določenega
- komentarja
- DELETE /lokacije/idLokacije/komentarji
- idLokacije ,
- idKomentarja
- http://edugeocache.si/api/
- lokacije/123/komentarji/abc
- 11.2.4 Odgovor (podatek in status) APIja
- Dobra praksa pri uporabi APIja je, da pri vsaki zahtevi dobimo odgovor, ki je sestavljen
- iz podatkov in HTTP šifre statusa. API podatke ponavadi vrača v XML ali JSON obliki.
- V našem primeru bomo uporabljali JSON obliko, ki je skladna z uporabljeno MEAN
- arhitekturo, prav tako pa zahteva prenos manjše količine podatkov kot XML oblika. Pri
- odgovoru odjemalec vedno pričakuje tudi HTTP šifro statusa, najbolj pogosto
- uporabljene so zbrane v tabeli 11.5.
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 32/45
- Tabela 11.5: HTTP šifre statusa
- Šifra
- statusa
- Naziv Primer uporabe
- 200 OK Uspešna GET ali PUT zahteva.
- 201 Created Uspešna POST zahteva.
- 204 No content Uspešna DELETE zahteva.
- 400 Bad request
- Neuspešna GET , POST ali PUT zahteva, zaradi
- napačne vsebine.
- 401 Unauthorized
- Zahteva zaščitenega URL naslova z napačnimi
- prijavnimi podatki.
- 403 Forbidden Zahteva, ki ni dovoljena.
- 404 Not found
- Neuspešna zahteva, zaradi napačnega parametra
- v URL naslovu.
- 405
- Method not
- allowed
- Metoda zahteve ni dovoljena za zahtevan URL
- naslov.
- 409 Conflict
- Neuspešna POST zahteva, ko že obstaja objekt z
- istimi podatki.
- 500
- Internal server
- error
- Težava s strežnikom ali podatkovno bazo.
- Verjetno je največ uporabnikom poznana šifra statusa , ki predstavlja neuspešno
- zahtevo, ko določene strani, ki jo uporabnik zahteva, ni mogoče najti. Vendar to še
- zdaleč ni edina, ampak obstajajo še številne druge, povezane z napakami na strani
- odjemalca oz. strežnika, preusmeritve in uspešne zahteve, kot je razvidno iz tabele
- 11.5.
- 11.3 Implementacija APIja z ogrodjem Express
- Aplikacijo smo že začeli graditi s pomočjo ogrodja Express, zdaj pa bi želeli dodati še
- dostop do podatkovne baze s pomočjo dostopa preko REST APIja. Cilj je ločitev
- dostopa do podatkovne baze od aplikacije, zato bomo celotno izvorno kodo, povezano
- z implementacijo APIja, hranili v mapi app_api .
- 404
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 33/45
- $ cd ~/workspace/edugeocache
- $ mkdir app_api
- $ cd app_api
- $ mkdir routes
- $ mkdir controllers
- 11.3.1 Priprava usmerjevalnika
- V začetno datoteko naše aplikacije app.js dodamo referenco na usmerjevalnik v
- okviru implementacije APIja.
- app.js
- 10
- 11
- 12
- var index = require('./app_server/routes/index');
- + var indexApi = require('./app_api/routes/index');
- var users = require('./app_server/routes/users');
- V aplikacijo dodamo tudi preusmeritev vseh zahtev /api na pravkar opredeljen
- usmerjevalnik indexApi .
- app.js
- 22
- 23
- 24
- app.use('/', index);
- + app.use('/api', indexApi);
- app.use('/users', users);
- Nato kreiramo novo datoteko app_api/routes/index.js , kjer bo implementiran
- usmerjevalnik za API. Izvorna koda usmerjevalnika je neposredna implementacija
- predvidenih poti za lokacije (glej tabelo 11.3 in vrstice 6 11) in komentarje (glej
- tabelo 11.4 in vrstice 13 21).
- app_api/routes/index.js
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 34/45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- var express = require('express');
- var router = express.Router();
- var ctrlLokacije = require('../controllers/lokacije');
- var ctrlKomentarji = require('../controllers/komentarji');
- // Lokacije
- router.get('/lokacije', ctrlLokacije.lokacijeSeznamPoRazdalji);
- router.post('/lokacije', ctrlLokacije.lokacijeKreiraj);
- router.get('/lokacije/:idLokacije', ctrlLokacije.lokacijePreberiIzbrano)
- router.put('/lokacije/:idLokacije', ctrlLokacije.lokacijePosodobiIzbrano
- router.delete('/lokacije/:idLokacije', ctrlLokacije.lokacijeIzbrisiIzbrano
- // Komentarji
- router.post('/lokacije/:idLokacije/komentarji',
- ctrlKomentarji.komentarjiKreiraj);
- router.get('/lokacije/:idLokacije/komentarji/:idKomentarja',
- ctrlKomentarji.komentarjiPreberiIzbranega);
- router.put('/lokacije/:idLokacije/komentarji/:idKomentarja',
- ctrlKomentarji.komentarjiPosodobiIzbranega);
- router.delete('/lokacije/:idLokacije/komentarji/:idKomentarja',
- ctrlKomentarji.komentarjiIzbrisiIzbranega);
- module.exports = router;
- Pri opredelitvi API URL naslova se pogosto uporabljajo parametri, s katerimi določimo
- odvisne dokumente, kot je to v našem primeru komentarjev, ki so odvisni od lokacije.
- Vključitev parametra v URL naslov je preprosta in sicer imenu spremenljivke samo
- dodamo predpono dvopičja : .
- 11.3.2 Priprava osnutka krmilnika
- Pri pripravi osnutka usmerjevalnika moramo pripraviti začetno kodo, da bo API sploh
- deloval, funkcionalnosti pa dejansko v krmilniku ne bo implementirane nobene, zgolj
- vračanje enostavnega besedila uspešno . Pri tem bomo uporabili preprosto metodo
- vrniJsonOdgovor , ki mu bomo podali parametra status odgovora in vsebina
- odgovora.
- V nadaljevanju bomo zato pripravili metode v obeh krmilnikih
- app_api/controllers/lokacije.js in app_api/controllers/komentarji.js .
- app_api/controllers/lokacije.js
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 35/45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- var vrniJsonOdgovor = function(odgovor, status, vsebina) {
- odgovor.status(status);
- odgovor.json(vsebina);
- };
- module.exports.lokacijeSeznamPoRazdalji = function(zahteva, odgovor) {
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- module.exports.lokacijeKreiraj = function(zahteva, odgovor) {
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- module.exports.lokacijePreberiIzbrano = function(zahteva, odgovor) {
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- module.exports.lokacijePosodobiIzbrano = function(zahteva, odgovor) {
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- module.exports.lokacijeIzbrisiIzbrano = function(zahteva, odgovor) {
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- app_api/controllers/komentarji.js
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- var vrniJsonOdgovor = function(odgovor, status, vsebina) {
- odgovor.status(status);
- odgovor.json(vsebina);
- };
- module.exports.komentarjiKreiraj = function(zahteva, odgovor) {
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- module.exports.komentarjiPreberiIzbranega = function(zahteva, odgovor) {
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- module.exports.komentarjiPosodobiIzbranega = function(zahteva, odgovor)
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- module.exports.komentarjiIzbrisiIzbranega = function(zahteva, odgovor) {
- vrniJsonOdgovor(odgovor, 200, {"status": "uspešno"});
- };
- 11.3.3 Vključitev modela
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 36/45
- Za API je ključnega pomena, da ima dostop do podatkovne baze, saj nam v
- nasprotnem primeru ne bi veliko koristil. Dostop do podatkovne baze imamo omogočen
- preko modelov, ki pa so trenutno vključeni v strežniško aplikacijo, ki se nahaja v mapi
- app_server . Ta strežniška aplikacija neposrednega dostopa do podatkovne baze
- preko modelov ne bo potrebovala, saj bo do podatkov dostopala posredno preko API
- vmesnika. Zaradi tega lahko prenesemo celotno mapo z modeli iz
- app_server/models v app_api/models .
- $ mv ~/workspace/edugeocache/app_server/models ~/workspace/edugeocache/app_api/models
- Zato moramo popraviti poti v osrednji aplikaciji app.js .
- app.js
- 8 * require('./app_api/models/db');
- Nato dodamo odvisnost v krmilnike APIja v datotekah
- app_api/controllers/lokacije.js in app_api/controllers/komentarji.js .
- app_api/controllers/lokacije.js
- 1
- 2
- + var mongoose = require('mongoose');
- + var Lokacija = mongoose.model('Lokacija');
- app_api/controllers/komentarji.js
- 1
- 2
- + var mongoose = require('mongoose');
- + var Lokacija = mongoose.model('Lokacija');
- 11.3.4 Testiranje
- Za testiranje enostavnih GET zahtev lahko uporabimo kar spletni brskalnik, kamor
- vnesemo željeni URL naslov in dobimo pričakovan odgovor, kot je to prikazano na sliki
- 11.11.
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 37/45
- Slika 11.11: Testiranje REST API GET zahteve /lokacije/1234
- Za bolj kompleksno testiranje vseh metod API vmesnika pa priporočamo bolj napredno
- orodje, kot je npr. Postman, ki nam omogoča napredno simuliranje različnih REST
- klicev in je v osnovni različici na voljo brezplačno.
- 11.4 GET metode za branje podatkov iz
- MongoDB
- Get metode se pri REST API vmesniku uporabljajo za poizvedovanje po podatkovni
- bazi in vračanje rezultatov poizvedb. V našem primeru imamo v usmerjevalniku
- app_api/routers/index.js opredeljene 3 GET metode, kot je prikazano v tabeli 11.6.
- Tabela 11.6: 3 GET metode v okviru aplikacije edugeocache
- Akcija Metoda URL naslov Parametri Primer
- Branje
- seznama
- lokacij
- GET /lokacije
- http://edugeocache.si/api/
- lokacije
- Branje
- določene
- lokacije
- GET /lokacije idLokacije
- http://edugeocache.si/api/
- lokacije/123
- Branje
- določenega
- komentarja
- GET /lokacije/idLokacije/komentarji
- idLokacije ,
- idKomentarja
- http://edugeocache.si/api/
- lokacije/123/komentarji/abc
- 11.4.1 Iskanje dokumenta
- Mongoose dostopa do podatkovne baze preko modelov, kar je tudi razlog, da smo
- model Lokacije vključili v oba krmilnika app_api/controllers/komentarji.jsi in
- app_api/controllers/lokacije.js .
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 38/45
- MongoDB preko dostopa z Mongoose ima na voljo številne metode za iskanje
- podatkov, kjer so ključne naslednje:
- find se uporablja za splošno iskanje, glede na podan filter iskanja,
- findById išče dokument s podanim enoličnim identifikatorjem,
- findOne vrne prvi rezultat ujemanja podanega filtra iskanja,
- geoNear išče zadetke, ki so geografsko blizu podani zemljepisni širini in dolžini,
- geoSearch vključi dodatne omejitve pri iskanju geoNear .
- Za potrebe iskanja določene lokacije bomo uporabili metodo findById .
- app_api/controllers/lokacije.js
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- + module.exports.lokacijePreberiIzbrano = function(zahteva, odgovor) {
- + Lokacija
- + .findById(zahteva.params.idLokacije)
- + .exec(function(napaka, lokacija) {
- * vrniJsonOdgovor(odgovor, 200, lokacija);
- + })
- + };
- Sedaj lahko preverimo delovanje metode tako, da najprej ugotovimo ID lokacije iz
- MongoDB podatkovne baze.
- $ mongo
- MongoDB shell version v3.4.10
- connecting to: mongodb://127.0.0.1:27017
- MongoDB server version: 3.4.10
- > use edugeocache
- switched to db edugeocache
- > db.Lokacije.find()
- { "_id" : ObjectId("5a0edde9490d6caf4cf68227"), ... }
- Nato s pomočjo IDja dokumenta sestavimo zahtevo, ki nam vrne zahtevano lokacijo iz
- podatkovne baze preko REST APIja.
- https://sp‐2017‐2018‐priprave‐dejanl.c9users.io/api/lokacije/5a0edde9490d6caf4cf68227
- 132
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 39/45
- 11.4.1.1 Obvladovanje napak
- Trenutna težava naše implementacije je, da vrne zgolj uspešen odgovor, v primeru
- neuspešne zahteve pa ne. Dobra praksa pri pripravi APIja je obvladovanje in lovljenje
- napak, zato moramo poskrbeti tudi za to in odjemalcu vedno vrniti odgovor, tudi ko
- pride do napake. V našem primeru lahko pride do naslednjih napak:
- med parametri zahteve ni idLokacije (glej vrstico 18),
- metoda findById ne vrne nobene lokacije (glej vrstice od 22 do 25) in
- med izvajanje metode findById pride do napake (glej vrstice od 26 do 28).
- app_api/controllers/lokacije.js
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- module.exports.lokacijePreberiIzbrano = function(zahteva, odgovor) {
- + if (zahteva.params && zahteva.params.idLokacije) {
- Lokacija
- .findById(zahteva.params.idLokacije)
- .exec(function(napaka, lokacija) {
- + if (!lokacija) {
- + vrniJsonOdgovor(odgovor, 404, { "sporočilo":
- + "Ne najdem lokacije s podanim enoličnim identifikatorjem idLokacije."
- + return;
- + } else if (napaka) {
- + vrniJsonOdgovor(odgovor, 404, napaka);
- + return;
- + }
- * vrniJsonOdgovor(odgovor, 200, lokacija);
- });
- + } else {
- + vrniJsonOdgovor(odgovor, 404, { "sporočilo":
- + "Manjka enolični identifikator idLokacije"});
- + }
- + };
- 11.4.2 Iskanje odvisnega dokumenta
- Komentarji so v našem primeru shranjeni kot deli dokumenta lokacije (odvisni
- dokumenti), tako da moramo najprej poiskati lokacijo, nato pa v tem dokumentu
- poiskati ustrezen komentar. Pri implementaciji metode komentarjiPreberiIzbranega v
- krmilniku app_api/controllers/komentarji.js si lahko pomagamo z implementacijo
- metode lokacijePreberiIzbrano iz prejšnjega poglavja. Ker ne potrebujemo vseh
- podatkov lokacije, lahko že v poizvedbi z uporabo .select('atribut1 atribut2 ...')
- omejimo, katere podatke potrebujemo (glej vrstico 17). Prav tako je v okviru MongoDB
- na voljo metoda id , s pomočjo katere lahko iščemo odvisne dokumente glede na
- podan enolični identifikator (glej vrstico 30).
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 40/45
- app_api/controllers/komentarji.js
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- module.exports.komentarjiPreberiIzbranega = function(zahteva, odgovor)
- + if (zahteva.params && zahteva.params.idLokacije && zahteva.params.idKomentarja
- + Lokacija
- + .findById(zahteva.params.idLokacije)
- + .select('naziv komentarji')
- + .exec(
- + function(napaka, lokacija) {
- + var rezultat, komentar;
- + if (!lokacija) {
- + vrniJsonOdgovor(odgovor, 404, { "sporočilo":
- + "Ne najdem lokacije s podanim enoličnim identifikatorjem idLokacije."
- + return;
- + } else if (napaka) {
- + vrniJsonOdgovor(odgovor, 404, napaka);
- + return;
- + }
- + if (lokacija.komentarji && lokacija.komentarji.length > 0) {
- + komentar = lokacija.komentarji.id(zahteva.params.idKomentarja
- + if (!komentar) {
- + vrniJsonOdgovor(odgovor, 404, { "sporočilo":
- + "Ne najdem komentarja s podanim enoličnim identifikatorjem idKomentarja"
- + } else {
- + rezultat = {
- + lokacija: { naziv: lokacija.naziv, id: zahteva.params.
- + komentar: komentar
- + };
- * vrniJsonOdgovor(odgovor, 200, rezultat);
- + }
- + } else {
- + vrniJsonOdgovor(odgovor, 404, { "sporočilo": "Ne najdem nobenega komentarja."
- + }
- + }
- + )
- + } else {
- + vrniJsonOdgovor(odgovor, 404, { "sporočilo":
- + "Ne najdem zapisa, oba enolična identifikatorja idLokacije in idKomentarja sta zahtevana."
- + }
- };
- Sedaj lahko preverimo delovanje metode tako, da najprej ugotovimo ID lokacije in ID
- komentarja iz MongoDB podatkovne baze.
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 41/45
- $ mongo
- MongoDB shell version v3.4.10
- connecting to: mongodb://127.0.0.1:27017
- MongoDB server version: 3.4.10
- > use edugeocache
- switched to db edugeocache
- > db.Lokacije.find()
- { "_id" : ObjectId("5a0edde9490d6caf4cf68227"), ... , "komentarji" : [ { "_id" : ObjectId(
- Nato s pomočjo IDja dokumenta sestavimo zahtevo, ki nam vrne zahtevano lokacijo iz
- podatkovne baze preko REST APIja.
- https://sp‐2017‐2018‐priprave‐dejanl.c9users.io/api/lokacije/5a0edde9490d6caf4cf68227/komentarji/5a0eddf719cf41316c98ccb4
- 11.4.3 Geografsko iskanje več dokumentov
- Spletna stran aplikacije naj bi prikazala seznam zanimivih lokacij, glede na trenutni
- položaj uporabnika. MongoDB ima na voljo nekaj geografskih funkcij iskanja, ki nam
- bodo to opravilo olajšale.
- Zahteva za prikaz lokacij je opremljena s parametrom lng in lat , kot prikazuje
- naslednji primer zahteve.
- /api/lokacije?lng=15.271601&lat=46.219849&maxRazdalja=100
- Pri zahtevi imamo na voljo naslednje parametre:
- obvezni parameter lng predstavlja zemljepisno dolžino,
- obvezni parameter lat predstavlja zemljepisno širino in
- opcijski parameter maxRazdalja predstavlja omejitev iskanja, do katere največje
- razdalje (v km) od podane točke naj vrača rezultate (privzeta vrednost je 20 km).
- Pri izvajanju geografskih iskanj, moramo vedno poskrbeti za omejevanje števila
- rezultatov. V okviru iskanja po MongoDB podatkovni bazi imamo na voljo dve možnosti:
-
-
-
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 42/45
- število zadetkov num in
- razdalja od začetne točke maxDistance , kjer je pričakovana vrednost v metrih (to
- smo uporabili v našem primeru).
- Celotna implementacija funkcije za prikaz najbližjih lokacij lokacijeSeznamPoRazdalji s
- pomočjo MongoDB funkcije geoNear je prikazana spodaj:
- app_api/controllers/lokacije.js
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- module.exports.lokacijeSeznamPoRazdalji = function(zahteva, odgovor) {
- + var lng = parseFloat(zahteva.query.lng);
- + var lat = parseFloat(zahteva.query.lat);
- + var razdalja = parseFloat(zahteva.query.maxRazdalja);
- + razdalja = isNaN(razdalja) ? 20 : razdalja;
- + var tocka = {
- + type: "Point",
- + coordinates: [lng, lat]
- + };
- + var geoParametri = {
- + spherical: true,
- + maxDistance: razdalja * 1000,
- + num: 10
- + };
- + if ((!lng && lng !== 0) || (!lat && lat !== 0)) {
- + vrniJsonOdgovor(odgovor, 404, { "sporočilo": "Parametra lng and lat sta obvezna."
- + return;
- + }
- + Lokacija.geoNear(tocka, geoParametri, function(napaka, rezultati) {
- + var lokacije = [];
- + if (napaka) {
- + vrniJsonOdgovor(odgovor, 404, napaka);
- + } else {
- + rezultati.forEach(function(dokument) {
- + lokacije.push({
- + razdalja: dokument.dis / 1000,
- + naziv: dokument.obj.naziv,
- + naslov: dokument.obj.naslov,
- + ocena: dokument.obj.ocena,
- + lastnosti: dokument.obj.lastnosti,
- + _id: dokument.obj._id
- + });
- + });
- * vrniJsonOdgovor(odgovor, 200, lokacije);
- + }
- + });
- };
- Sedaj lahko preverimo delovanje metode s testno zahtevo, kjer kot začetno točko
- podamo GPS koordinate lokacije Stari grad Celje in zahtevamo lokacije v radiju 100
- km.
- https://sp‐2017‐2018‐priprave‐dejanl.c9users.io/api/lokacije?lng=15.271601&lat=46.219849
- 1/9/2018 Spletno programiranje 2017/2018
- https://teaching.lavbic.net/SP/20172018/MongoDBMongooseREST.html 43/45
- Kot odgovor dobimo pričakovana 2 zadetka, Stari grad Celje na razdalji 0 km in ZOO
- Ljubljana na razdalji ~ 64 km.
- [
- {
- "razdalja": 0,
- "naziv": "Stari grad Celje",
- "naslov": "Cesta na grad 78, 3000 Celje, Slovenija",
- "ocena": 3,
- "lastnosti": ["slikovit razgled", "vstopnina", "otrokom prijazno"],
- "_id": "5a0edde9490d6caf4cf68227"
- }, {
- "razdalja": 64.41779956859011,
- "naziv": "ZOO Ljubljana",
- "naslov": "Večna pot 70, 1000 Ljubljana, Slovenija",
- "ocena": 4,
- "lastnosti": [ "priporočljivo za otroke", "živali", "parkirišče je na voljo", "vstopnina"
- "_id": "5a0edde9490d6caf4cf68229"
- }
- ]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement