+ All Categories
Home > Documents > DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS...

DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS...

Date post: 23-Mar-2021
Category:
Upload: others
View: 3 times
Download: 0 times
Share this document with a friend
17
DA DATA TA S SCALABLE CALABLE S SOLUTIONS OLUTIONS FOR FOR I I NDUSTRIAL NDUSTRIAL A APPLICATIONS PPLICATIONS (DASSIA) (DASSIA) T UTORIAL UTORIAL MONGODB MONGODB Tutorial_MongoDB 1 di 17
Transcript
Page 1: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

DADATATA S SCALABLECALABLE S SOLUTIONSOLUTIONS FORFOR I INDUSTRIALNDUSTRIAL A APPLICATIONSPPLICATIONS (DASSIA) (DASSIA)

TTUTORIALUTORIAL

MONGODB MONGODB

Tutorial_MongoDB 1 di 17

Page 2: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

1 ESPLORAZIONE BASE DI MONGODB

Le attività di questo tutorial sono orientate all'illustrazione di alcuni comandi principali, illustrati nella parte teorica,

per l'esecuzione di query di MongoDB in modo da illustrare meglio diversi concetti.

Per fare questo useremo il tool RoboMongo come GUI per l'esecuzione delle query e due dataset (già precaricati in

Mongo) per l'illustrazione e spiegazione dei modelli di query (ne useremo uno come esempio e lasceremo l'altro come

dataset di test dove replicare query similari).

1.1 Interfaccia

Per interagire con Mongo useremo RoboMongo (http://robomongo.org/), questo è un tool open-source

multipiattaforma per la gestione di MongoDB. In pratica si tratta di una GUI per interagire con MongoDB con le

stesse potenzialità offerte dalla shell mongo, ovvero è presente lo stesso motore JavaScript che è presente nella shell e

si può utilizzare esattamente come se si stesse usando la shell mongo.

Per avviarlo nella vostra macchina virtuale avviatelo facendo doppio click sulla seguente icona

Verrà aperta la finestra di connessione al server che in questo caso è sulla stessa macchina.

Una volta cliccato su Connect si aprirà la seguente finestra

Tutorial_MongoDB 2 di 17

Page 3: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

Sulla sinistra abbiamo il server con tre DB (nba, test e usda), all'interno di ogni DB abbiamo le Collection ed

eventuali funzioni e utenti specifici per il database.

Per aprire una nuova shell possiamo aprire il menù contestuale premendo il pulsante destro sul nome del server e

scegliendo Open Shell, oppure espandendo l'albero alla voce Collections e facendo doppio click sul nome di una

collection. In quest'ultimo caso verrà in automatico aperta una shell con una query find() eseguita sulla collection.

A questo punto è possibile navigare fra tutti i Document contenuti nella collection od esplorare la struttura di

ciascuno di essi.

Si noti come nell'esempio sono presenti 3 tab: ognuno di essi è una shell mongo separata dalle altre.

E' possibile scrivere anche più query da eseguire, in questo modo verranno mostrati i risultati delle singole query in

schede separate.

Tutorial_MongoDB 3 di 17

Page 4: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

Tutorial_MongoDB 4 di 17

Page 5: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

2 DATASET DI ESEMPIO

All'interno della macchina virtuale sono stati precaricati due dataset: nba e usda.

2.1 Datatset nbaIl dataset nba contiene al suo interno i risultati e le statistiche sui giocatori delle regular season NBA a partire dalla

stagione 1985-1986 fino alla stagione 2012-2013.

I dati sono organizzati nel seguente modo:

abbiamo l'identificativo del documento _id, l'array box contentente le informazioni dei giocatori delle squadre, la

data del match in date, ed infine le informazioni delle squadre nell'array di document teams.

In quest'ultimo caso per ciascun document in teams sono disponibili i seguenti field

Nome (name), abbreviazione del nome (abbrebiation), punteggio finale (score), se il team era in casa (home) e se

ha vinto l'incontro (won).

Box contiene dei document strutturati nel seguente modo

Un array con tutti i giocatori e le loro statistiche (players), le statistiche sul team (team) ed un field che indica se il

team ha vinto l'incontro o meno (won). Le statistiche disponibili sono: assist (ast), stoppate (blk), canestri effettuati da

2 punti (fg), tiri effettuati da 2 punti (fga), percentuale di realizzazione da 2 punti (fg_pct), canestri effettuati da 3

punti (fg3), tiri effettuati da 3 punti (fg3a), percentuale di realizzazione da 3 punti (fg3_pct), tiri liberi realizzati (ft),

tiri liberi effettuati (fta), percentuale di realizzazione dei tiri liberi (ft_pct), minuti giocati (mp), rimbalzi

offensivi(orb), rimbalzi difensivi(drb), rimbalzi totali (trb), falli personali (pf), punti realizzati (pts), palloni rubati

(stl), cambi (tov), ed inoltre i document dei giocatori hanno il filed player che contiene il nome del giocatore.

Tutorial_MongoDB 5 di 17

Page 6: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

2.2 Dataset usdaIl dataset usda contiene dati estrapolati da “Composition of Foods Raw, Processed, Prepared USDA National

Nutrient Database for Standard Reference, Release 25” del governo americano, ovvero un dataset dei cibi presenti

negli Stati Uniti ed i loro nutrienti.

Il dataset è organizzato nel seguente modo:

A più altro livello abbiamo, l'identificativo dell'alimento (_id), a quale categoria appartiene (foodgGroup), la

descrizione (description), il produttore (manufacturer) e se l'alimento ha fatto parte di una survey sui nutrienti

effettuata dal governo americano (survey). Inoltre contiene due array di document (nutrients e weights).

Nei nutrients sono elencati tutti i nutrienti presenti nell'alimento e per ciascuno di questi è indicato il suo

identificativo (_id), l'unita di misura (units), una etichetta (tagname), una descrizione (description), e la presenza su

100g dell'alimento in termini dell'unità di misura espressa in precedenza (amountPer100G).

Tutorial_MongoDB 6 di 17

Page 7: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

Nei weights viene indicata la quantità di utilizzo comune in termini di quantità (amount) rispetto ad una data unità

di misura (unit) ed il corrispondente in grammi (grams).

Tutorial_MongoDB 7 di 17

Page 8: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

3 ESEMPI DI INTERROGAZIONE DEL DATABASE NBA

3.1 Query senza aggregazioneLe prime query che andremo a vedere sono quelle per cercare uno o più elementi all'interno di una collection.

3.1.1 Query find

La prima operazione che andiamo a svolgere è l'equivalente di una query SQL

SELECT * FROM games

per recuperare tutti i documenti della collection games del database nba. La query è la seguente:

db.games.find()

Nell'immagine vediamo tutti i document che sono stati restituiti e, tramite RoboMongo, abbiamo la possibilità di

esplorarli e vedere i successivi tramite i controlli

dove possiamo scorrere il cursore dei risultati e scegliere quanti elementi visualizzare ogni volta, in particolare la cifra

a sinistra indica il document da cui inizia la visualizzazione e la cifra a destra indica il numero di document

visualizzati.

Tutorial_MongoDB 8 di 17

Page 9: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

3.1.2 Query find: cursor modifier - limit

Se vogliamo recuperare un solo elemento dobbiamo scrivere la query:

db.games.findOne()

possiamo anche chiedere tutti gli elementi ma mostrare solo il primo e avremo il medesimo risultato

db.games.find().limit(1)

come possiamo vedere nella figura successiva.

3.1.3 Query find: cursor modifier - limit e skip

Recuperiamo ora solo il 4° ed il 5° document. Possiamo usare la seguente query dove saltiamo i primi tre elementi e

ne mostriamo due:

db.games.find().limit(2).skip(3)

nella figura vediamo il confronto anche con la query che recupera i primi 5 elementi per evidenziare che si tratta

effettivamente del 4° e 5° document.

Tutorial_MongoDB 9 di 17

Page 10: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

3.1.4 Query find: count

Contiamo ora il numero di document presenti in games aggiungendo l'operatore count nel seguente modo:

db.games.find().count()

dal quale dovrebbe risultare che il numero di document totali nel dataset è 31686.

Per sapere a quante partite ha preso parte il giocatore Dominque Wilkins possiamo usare.

db.games.find({"box.players.player":"Dominique Wilkins"}).count()

che equivale a scrivere in SQL

SELECT COUNT(*) FROM games WHERE box.players.player=”Dominique Wilkins”.

3.1.5 Query find: projection

Se volessimo visualizzare solo dei campi specifici, ad esempio solo l'_id ed il field date dovremmo usare

l'interrogazione:

db.games.find({},{_id:1,"date":1})

che equivale a scrivere in SQL

SELECT _id,date FROM games

Ricordiamo che in mongo all'atto della proiezione il field _id viene sempre restituito, quindi se non volessimo

visualizzarlo dovremmo indicarlo esplicitamente:

db.games.find({},{_id:0,"date":1})

3.1.6 Query find: Query Criteria

Supponiamo ora di voler recuperare le sole partite dei Los Angeles Lakers:

db.games.find({"teams.name":"Los Angeles Lakers"})

che equivale alla query SQL

SELECT * FROM games WHERE teams.name=”Los Angeles Lakers”.

Se vogliamo sapere quante sono le partite giocate dai Los Angeles Lakers basta aggiungere count() in coda alla

query precedente: otteniamo 2257 match.

Tutorial_MongoDB 10 di 17

Page 11: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

3.1.7 Query find: Regular Expression

Se vogliamo restituire tutte le partite delle squadre di Los Angeles (e non solo dei Lakers):

db.games.find({"teams.name":/Los Angeles/})

per effettuare le ricerche nei testi MongoDB utilizza le espressioni regolari, in questo modo è possibile riprodurre il

funzionamento dell'operatore LIKE dell'SQL.

3.1.8 Operatore distinct

Per sapere quali sono i nomi delle squadre presenti nella collection utilizziamo l'operatore distinct

db.games.distinct("teams.name")

stessa cosa se volessimo trovare i nomi di tutti i giocatori.

db.games.distinct("box.players.player")

Tuttavia non è possibile concatenare l'operatore count a distinct. Quindi, per ottenere il numero di giocatori distinti,

dobbiamo sfruttare il JavaScript ed eseguire i seguenti comandi

var x = db.games.distinct("box.players.player");

x.length

3.1.9 Query find: sort

Per cercare il punteggio massimo (o minimo) tra tutte le partite NBA, a differenza di quanto succede con SQL, non

abbiamo a disposizione l'operatore MAX e MIN. Per ottenere l'equivalente di una semplice query:

SELECT MAX(teams.score) FROM games

in Mongo dobbiamo usare un metodo meno diretto:

• ordinare i dati in modo ascendente/discendente;

• prendere il primo elemento oppure usare una funzione di aggregazione.

Per eseguire la prima operazione, quella di ordinamento (sort), la nostra query è la seguente:

db.games.find().sort({"teams.score":1})

Eseguendola nella virtual machine otteniamo il seguente errore

Tutorial_MongoDB 11 di 17

Page 12: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

Questo perché MongoDB ha un limite di 32MB di RAM per le operazioni di sort in memoria. Questo limite è

intenzionale perché vuole spingere l'utente a definire degli indici secondari sui campi utilizzati per operazioni che

richiedono la costruzione in ram di indici temporanei (ordinamento e aggregazione, in quest'ultimo caso il limite è

posto a 100MB).

3.1.10 Indici secondari

Se vogliamo creare un indice secondario in modo da poter recuperare tutti i document ordinati sulla base del campo

score:

db.games.ensureIndex({"teams.score":1})

Dopo aver creato l'indice possiamo interrogare la collection con il comando sort senza preoccuparci dei limiti

evidenziati al paragrafo precedente:

db.games.find().sort({"teams.score":1})

3.2 Query con aggregazioneNei paragrafi precedenti abbiamo visto come effettuare alcune semplici query: vediamo ora come realizzare qualche

query complessa sfruttando l'aggregazione.

Supponiamo si vogliano cercare tutte le partite vinte dai Los Angeles Lakers, probabilmente il primo istinto,

soprattutto se si proviene dal mondo SQL, è quello di scrivere una query di questo tipo:

db.games.find({"teams.name":"Los Angeles Lakers"},{"teams.won":1})

certi della sua equivalenza alla query SQL

SELECT * FROM games WHERE teams.name='Los Angeles Lakers' AND teams.won=1

La query di per sé è corretta e, in fase di esecuzione, non vengono evidenziati degli errori. Il risultato ottenuto però

non è quello che ci sia aspetta, infatti, se si guarda l'immagine successiva, si vede come il numero di gare restituito

coincide esattamente col numero di gare disputate dai Los Angeles Lakers (come da esempio riportato nel paragrafo

3.1.6) e non è invece limitato alle sole partite vinte.

Tutorial_MongoDB 12 di 17

Page 13: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

L'errore in questo caso è di tipo concettuale dovuto all'adattamento della query al modello documentale.

Nel dataset NBA all'interno del medesimo document sono contenuti i dati di ogni singola partita, sia quelli della

squadra vincente che quelli della squadra perdente: quindi all'interno del document ci sarà sempre il valore

teams.won = 1.

Per far si di avere le informazioni relative solamente alle vittorie dei Los Angeles Lakers dobbiamo costruire una

query di aggregazione e sfruttare lo stage $unwind. Questo stage ci consente di separare un document in document

differenti in base ad uno specifico field selezionato.

Ad esempio se applichiamo l'operatore $unwind all'array teams otterremo, per ogni document che rappresenta una

partita, due document che saranno identici tranne che per il field teams: uno conterrà la squadra vincente ed uno quella

sconfitta.

Tutorial_MongoDB 13 di 17

Page 14: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

La query corretta è dunque la seguente

db.games.aggregate(

{$unwind:"$teams"},

{$match:{"teams.name":"Los Angeles Lakers" , "teams.won":1}},

{$group:{_id:"$teams.name", "won_games":{$sum:1}}}

)

Ricordiamo che lo stage $match opera sul risultato dello stage precedente e serve per selezionare i document in base

ai criteri in esso contenuti, mentre lo stage $group in questo caso lavora sui dati in uscita dalla pipeline dopo

$match e raggruppa in base al field specificato in _id (obbligatorio, può essere anche null) e per ciascun team

restituisce il numero di document corrispondente ($sum:1).

Tutorial_MongoDB 14 di 17

Page 15: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

3.2.1 Aggregazione: pipeline di stage

Complicando l'interrogazione precedente, se volessimo trovare le tre squadre che hanno vinto più partite nella regular

season dovremmo scrivere la seguente query

db.games.aggregate(

{$unwind:"$teams"},

{$match:{"teams.won":1}},

{$group:{_id:"$teams.name", "won_games":{$sum:1}}},

{$sort:{"won_games":-1}},

{$limit:3}

)

Tutorial_MongoDB 15 di 17

Page 16: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

3.3 Query con aggregazione map - reduceNegli esempi precedenti abbiamo visto come fare operazioni di aggregazione. Vediamo ora un esempio più complesso

e la sua implementazione tramite map-reduce in MongoDB.

L'interrogazione che si vuole eseguire è la seguente:

trovare la media di canestri da tre punti dei giocatori NBA calcolata su tutte le partite giocate

3.3.1 Funzione MAP

Per prima cosa dobbiamo creare la funzione map. Questa associa ad ogni giocatore i punti da tre realizzati in una

specifica partita.

var mapFunction = function() {

for(var idx = 0; idx < this.box.length; idx++) {

for(var id2 = 0; id2 < this.box[idx].players.length; id2++) {

var key = this.box[idx].players[id2].player;

var value = { count: 1,

fg3 : this.box[idx].players[id2].fg3};

emit(key,value);

}

}

}

In questo caso la funzione map emetterà una serie di coppie chiave-valore, il field count ci servirà per “contare” il

numero di partite.

3.3.2 Funzione REDUCE

La funzione reduce si occuperà di aggregare i dati ottenuti dal map. Ricordiamo che la funzione reduce deve essere

idempotente e, soprattutto, che l'oggetto restituito deve essere identico al tipo di quello emesso dal map.

var reduceFunction = function(key, values) {

var reducedVal = {count:0, fg3: 0}

for (var idx = 0; idx < values.length; idx++) {

reducedVal.count += values[idx].count;

reducedVal.fg3 += values[idx].fg3;

}

Tutorial_MongoDB 16 di 17

Page 17: DATA SCALABLE SOLUTIONS FOR INDUSTRIAL PPLICATIONS …dassia.crs4.it/wp-content/uploads/2014/11/Tutorial_Mongo... · 2015. 2. 26. · Le prime query che andremo a vedere sono quelle

return reducedVal;

}

3.3.3 Funzione FINALIZE

A questo punto abbiamo associato ad ogni giocatore il numero di partite in cui era presente e la somma di punti da tre

realizzati. La media dei punti la calcoliamo tramite la funzione finalize che ci permette di aggiungere un campo dove

inserire la media dei punti.

var finalizeFunction = function (key, reducedVal) {

reducedVal.avg = reducedVal.fg3/reducedVal.count;

return reducedVal;

}

3.3.4 MapReduce in MongoDB

Una volta definite queste funzioni non rimane che chiamare il metodo map-reduce di MongoDB e salvare il risultato

in una nuova collection.

db.games.mapReduce(

mapFunction,

reduceFunction,

{

out: "three_points",

finalize : finalizeFunction

}

)

Tutorial_MongoDB 17 di 17


Recommended