Upload
others
View
4
Download
0
Embed Size (px)
Citation preview
NOSQL
MongoDB
Origini
MongoDB deriva il suo nome dalla parola "huMONGOus”, che significa enorme. E'
attualmente il il database NoSQL più diffuso*.
Sviluppato inizialmente dalla società di software 10gen (ora MongoDB Inc.) nel 2007
come un componente di un altro prodotto. Nel 2009 viene rilasciato in open-source
come database a se stante. *Fonte del dato della diffusione dei DB: http://db-engines.com/en/ranking
MongoDB
Datamodel
MongoDB è un document store: ogni record viene memorizzato come un documento;
esso può avere un numero arbitrario di campi aventi una qualsiasi lunghezza.
Rispetto al modello relazionale: si accorpano quanto più possibile gli oggetti, creando
delle macro entità dal massimo contenuto informativo.
MongoDB non possiede uno schema e ogni documento non è strutturato, ha solo una
chiave obbligatoria: _id , la quale è utilizzata per identificare univocamente il
documento.
MongoDB
BSON e JSON
Il formato utilizzato per il salvataggio e la trasmissione dei document in MongoDB è il
BSON (JSON Binario).
Il formato JSON (JavaScript Object Notation) è largamente diffuso nel mondo web,
esso è un formato di testo completamente indipendente dal linguaggio di
programmazione utilizzato ed è basato su due strutture:
- un insieme di coppie nome/valore;
- un elenco ordinato di valori.
MongoDB
Esempio di JSON
{
"_id" : 1,
"name" : { "first" : "John", "last" : "Backus" },
"contribs" : [ "Fortran", "ALGOL", "Backus-Naur Form", "FP" ],
"awards" : [
{
"award" : "W.W. McDowell Award",
"year" : 1967
},
{ "award" : "Draper Prize",
"year" : 1993
}
]
}
MongoDB
BSON e JSON
II formato BSON estende il modello JSON allo scopo di aggiungere ulteriori tipi di dati
(ad esempio il formato data e il byte array) e garantire una maggiore efficienza
nell'interazione tra diversi linguaggi di programmazione.
La dimensione massima di un singolo documento BSON è di 16MB.
Ad ogni document è associato un _id che agisce come object identifier ed è composto
da 12 byte come segue:
MongoDB
BSON e GridFS
La dimensione del BSON potrebbe essere limitante.
Si può utilizzare la modalità in GridFS che, invece che effettuare un'unica
memorizzazione, divide i file in più parti (chunk) di dimensione prestabilita e li
memorizza come document separati.
Il limite di default di un chunk è 255kB.
Vengono utilizzate due collection per memorizzare i file:
- una per i chunk;
- una per i metadati.
Sarà compito del driver o del client riassemblare i chunk necessari.
MongoDB
Datamodel
In MongoDB il document è l'unità di base del database ed equivale ad una riga dei
database relazionali.
La tabella seguente riassume le “equivalenze” di termini fra MongoDB e gli RDBMS:
MongoDB RDBMS
Database Database
Collection Tabella
Document Record
Field Colonna
MongoDB
Datamodel
Database
Collection
Collection
DocumentDocument_idField1Field3Field4
DocumentDocument_idField1Field2
Collection
Architettura
MongoDB
Architettura Base
MongoDB è organizzato secondo una architettura base Client/Server.
Il client può essere:
- shell mongo (implementata in JavaScript)
- un applicativo scritto in diversi linguaggi di programmazione
mongod
client
Oltre a questa configurazione base è possibile incrementare la ridondanza e la disponibilità del dato attraverso la configurazione di un “replica set”
MongoDB
Architettura con Replica Set
Un replica set è un gruppo di istanze mongod che
gestiscono lo stesso insieme di dati.
Tutte le modifiche che vengono effettuate
unicamente sul primary, vengono scritte in un log
che viene poi distribuito in maniera asincrona ai
secondary i quali poi replicano le modifiche sui loro
dati.
I client leggono i dati dal primary, ma possono
essere configurati anche per leggere i dati dai
secondary.
Il dato restituito da un secondary potrebbe non
essere aggiornato.
Replica set
client
Primary
Secondary Secondary
MongoDB
Architettura con Replica Set
Nel caso in cui il server primario non
fosse più disponibile un meccanismo
di automatic election provvede ad
eleggere un nuovo server primario fra
i secondari.
È possibile prevedere un'ulteriore
istanza di mongod, avente il ruolo di
arbiter, che viene utilizzato solo per la
votazione durante l'elezione del nuovo
primary.
Mongod: Primary
Mongod: Secondary
Mongod: SecondaryLettura
Lettura
Lettura
Scrittura
Driv
er Replicheasincrone
Lettura
Lettura
ScritturaDriv
erMongod: Primary
Mongod: Primary
Mongod: Secondary
Replicaasincrona
MongoDB
Introduzione Architettura Sharding
L'architettura appena vista presenta potenziali problemi:
- all'aumentare del numero di query è possibile che si possa esaurire la capacità di CPU
del server;
- all'aumentare delle dimensioni dei dati c'è il rischio di superare la capacità del disco di
una singola macchina;
- dati di lavoro di dimensioni superiori alla RAM del sistema potrebbero “stressare” la
velocità di I / O dei dischi .
Possibili soluzioni:
- scalare verticalmente (aumento CPU, HD e ram);
- scalare orizzontalmente (sharding).
MongoDB
Architettura Sharding
MongoDB può scalare orizzontalmente in maniera lineare.
L'architettura Sharding è costituita da tre componenti:
- Shards: immagazzinano i dati, per garantire la consistenza e la disponibilità dei dati
sono spesso costituiti da dei Replica Sets;
- Query Routers o istanze mongos: interfacce che ridirezionano le richieste verso i
shards corretti e restituiscono il risultato ai vari client.
- Config servers: contengono i metadati che descrivono il mapping tra dati e shards.
MongoDB
Architettura Sharding
Shard 1
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
Shard N
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
client
mongos mongos
Config
Config
Config
MongoDB
Architettura Sharding
Il partizionamento ed il bilanciamento è automatico in base alla Shard Key (un field
del document) che si decide di utilizzare.
È poi possibile decidere, per la suddivisione dei dati in chunks, se utilizzare:
Range Based Sharding Hash Based Sharding
mongod
Key-range (0...99)
mongod
Key-range (0...33)
mongod
Key-range (67...99)
mongod
Chunk 1 Chunk N
mongod
mongod mongodmongod
Chunk 1 Chunk N
Hash Function
Query Language
MongoDB
Datatype
Datatype Descrizione
Boolean Tipo booleano true/false
Arrays Utilizzato per memorizzare array o liste di valori
Integer Valori numerici (32-bit o 64-bit a seconda del server.
Double Valori numerici in virgola mobile
String Stringa in formato UTF-8
Symbol Come una stringa, ma utilizzato nei linguaggi che usano il tipo symbol (es. Ruby)
Regular expression Utilizzato per memorizzare espressioni regolari
Date Memorizza il tempo e la data in formato Unix.
Timestamp Memorizza un Timestamp
Binary data Memorizza dati in formato binario
Code Utilizzato per memorizzare codice Javascript nel document
Null Memorizza un valore null
Object ID Memorizza l'ID del document
Object Utilizzato per gli embedded document
Min/Max key Questi vengono usati solo internamente e servono per comparare al valore minimo e massimo di un dato BSON
MongoDB
Query Language – Uso dei database
Per selezionare un database:
> use DATABASE_NAME
Questo comando seleziona il database e, qualora non esista, lo crea.
Per vedere quali database sono presenti all'interno di un server possiamo usare il
comando
> show dbs
local 0.78125GB
test 0.23012GB
vengono mostrati tutti i database sui quali è stato fatto almeno un insert e la
dimensione che occupano.
MongoDB
Query Language – Uso dei database
Per sapere quale database è stato selezionato si usa il comando:
> db
viene restituito il nome del database in uso.
Per eliminare un database occorre selezionarlo attraverso use e poi dare il comando:
> db.dropDatabase()
se per caso non viene selezionato nessun database e viene dato il comando
db.dropDatabase viene eliminato il database di default.
MongoDB
Query Language – Collection
Una volta che abbiamo creato il database possiamo creare le collection al suo interno.
Possono essere usati due metodi:
- il primo prevede una creazione esplicita
> db.createCollection(name, options)
- il secondo prevede una creazione implicita
> db.users.insert(document)
Per visualizzare tutte le collection presenti in un database si usa il comando:
> show collections
MongoDB
Query Language - Insert
Con il comando insert possiamo inserire un document all'interno di una collection.
> db.docs.insert({
_id: ObjectId(7df78ad8902c),
title: 'Dispense MongoDB',
description: 'Dispense corso DASSIA su MongoDB',
by: 'CRS4',
url: 'http://dassia.crs4.it/',
tags: ['mongodb', 'database', 'NoSQL']
})
Se l'_id non viene specificato questo viene assegnato in maniera automatica.
MongoDB
Query Language - Find
Il metodo “base” per effettuare le query è find: restituisce un cursore ai dati
corrispondenti e supporta sia criteri per la query che le proiezioni dei dati.
Possono poi essere applicati dei modificatori al cursore.
MongoDB
SQL
db.users.find(
{ age: {$gt: 18 } },
{ name : 1, address: 1}
) . limit ( 5 )
SELECT _id, name, address
FROM users
WHERE age > 18
LIMIT 5
← collection
← criteri di query
← proiezione
← modificatore di cursore
← proiezione
← tabella
← criteri di selezione
← modificatore di cursore
MongoDB
Query Language - Find
L'uso del metodo find è il seguente
> db.COLLECTION_NAME.find({QueryCriteria},{Projection})
dove i QueryCriteria e la Projection sono opzionali.
Vanno racchiusi fra parentesi grafe e possono essere più di uno: eventuali criteri di
selezione vanno indicati singolarmente.
Se si vuole effettuare una proiezione senza criteri di selezione:
> db.COLLECTION_NAME.find({},{Projection})
Se non si ha nessuna proiezione da fare, ma solo delle selezioni la sintassi è
> db.COLLECTION_NAME.find({QueryCriteria})
MongoDB
Find – Query Criteria
Criterio Sintassi Esempio
Uguaglianza {<key>:<value>} db.users.find({“name” : “Nicola” })
Minore di {<key>:{$lt:<value>}} db.users.find({ age : {$lt:25}})
Minore o uguale di {<key>:{$lte:<value>}} db.users.find({ age : {$lte:25}})
Maggiore di {<key>:{$gt:<value>}} db.users.find({ age : {$gt:18}})
Maggiore o uguale di {<key>:{$gte:<value>}} db.users.find({ age : {$gte:19}})
Non uguale {<key>:{$ne:<value>}} db.users.find({ age : {$ne:45}})
MongoDB
Find – Query Criteria
Il metodo find supporta criteri multipli in AND, OR o combinazione di questi:
AND (tutti gli utenti di 18 anni che si chiamano Nicola)
> db.users.find({ age: 18, name: 'Nicola'})
OR (tutti gli utenti di 18 anni e tutti gli utenti che si chiamano Nicola)
> db.users.find({ $or: [{age: 18}, {name: 'Nicola'}] })
AND e OR (tutti gli utenti di 18 anni e che contemporaneamente si chiamano Nicola o vivono
a Cagliari)
> db.users.find({ age: 18,
$or:[ {name: 'Nicola'}, {town: 'Cagliari'} ]
})
MongoDB
Find – Projection
I criteri di proiezione servono ad indicare quali attributi del documento restituire.
db.users.find( { age: 18 } , { name: 1} )
Bisogna notare che _id viene sempre restituito, se non lo si vuole visualizzare va
messo a zero.
db.users.find( { age: 18 } , { name: 1, _id : 0} )
{ _id: 2, age: 28, name: 'Asia' }
{ _id: 3, age: 21, name: 'Giada' }
{ _id: 4, age: 38, name: 'Ugo' }
{ _id: 5, age: 18, name: 'Sofia' }
{ _id: 6, age: 58, name: 'Guido' }
{ _id: 1, age: 18, name: 'Almo' }
{ _id: 1, age: 18, name: 'Almo' }
{ _id: 5, age: 18, name: 'Sofia' }
{ _id: 1, name: 'Almo' }
{ _id: 5, name: 'Sofia' }
query criteria projection
MongoDB
Cursor Modifier: Limit e Skip
Il cursore ai dati restituito da un find può essere modificato mediante l'utilizzo di un cursor
modifier. Abbiamo quindi:
limit che viene utilizzato per restituire i primi N documenti trovati.
> db.COLLECTION_NAME.find().limit(N)
skip che permette di “saltare” i primi M documenti trovati.
> db.COLLECTION_NAME.find().skip(M)
Ad esempio
> db.users.find({},{name:1,_id:0}).limit(1).skip(2)
restituisce il nome del terzo documento.
MongoDB
Sort e Distinct
sort che esegue l'ordinamento per la chiave specificata ascendente (1) o discendente (-1)
> db.COLLECTION_NAME.find().sort({key:1})
distinct se volessi trovare tutti i valori diversi presenti per uno o più field in una collection
> db.COLLECTION_NAME.distinct('key')
Ad esempio, la seguente trova tutti i nomi presenti nella collection
> db.users.distinct('name')
mentre la seguente restituisce tutti i nomi distinti dei maggiorenni presenti nella collection
> db.users.distinct('name',{age:{$gte:18}})
MongoDB
Count
Per contare il numero di documenti può essere usato il metodo count() sia in questo
modo:
> db.COLLECTION_NAME.count()
che
> db.COLLECTION_NAME.find().count()
Se vogliamo specificare dei criteri di query, ricorrendo alla programmazione funzionale,
abbiamo:
db.users.count( { age: { $gt: 30 } })
oppure
db.users.find( { age: { $gt: 30 } }).count()
MongoDB
Update e Save
Per aggiornare un document si hanno due metodi a disposizione:
- update: aggiorna i field che vengono indicati nel document;
- save: rimpiazza il document esistente con uno nuovo.
Ad esempio abbiamo:
> db.users.update({name: 'Pino'}, {$set:{name: 'Ugo'}})
> db.users.save({_id:ObjectId(),NEW_DATA})
MongoDB
Remove Document
Per rimuovere un document si utilizza remove.
> db.COLLECTION_NAME.remove(DELETION_CRITERIA)
Ad esempio
> db.users.remove({name: 'Maurizio'})
Mentre la sintassi per rimuovere il primo document dove compare il criterio è:
> db.COLLECTION_NAME.remove(DELETION_CRITERIA, 1)
Per rimuovere tutti i document da una collection devo usare
> db.COLLECTION_NAME.remove()
MongoDB
Indici Secondari
Tutti i documenti sono indicizzati per la loro chiave primaria _id.
Ciò significa che utilizzando il metodo find con alcuni criteri di ricerca controlleremo tutti
i documenti nella loro interezza. Per snellire queste operazioni si possono creare degli
indici secondari tramite il comando ensureIndex.
> db.COLLECTION_NAME.ensureIndex(keys,options)
Posso ad esempio specificare uno o più field sui quali generare gli indici sia in maniera
ascendente (1) che discendente (-1).
> db.users.ensureIndex({'name' : 1, 'age' : -1})
MongoDB
Aggregazione
In MongoDB è possibile processare diversi dati per restituire dati aggregati o computazioni
sugli stessi.
> db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATIONS)
È presente il concetto di pipeline nell'aggregazione: possiamo definire una pipeline di stage
consecutivi per ridurre e filtrare i dati all'interno dell'aggregazione. Ad esempio abbiamo gli
stage per:
- $match: filtra dei dati in base a criteri assegnati
- $group: raggruppa i dati in base a criteri assegnati
- $unwind: separa un array del documento creando singoli documenti
- $projection: proietta i dati in base a criteri assegnati
- $sort: ordina i dati in base a criteri assegnati
- $limit: prende in esame solo i primi N document
- $skip: salta i primi N document
MongoDB
Aggregazione – Group
All'interno di $group possiamo utilizzare diverse espressioni per ottenere dati aggregati o
particolari computazioni sugli stessi:
$sum $avg $min $max $first $last $push $addtoset
Ad esempio:
db.users.aggregate( [ { $group:{_id:'$name', count_omonimi:{$sum:1} } } ])
db.users.aggregate( [ { $group:{_id:null, eta_min:{$min:'$age'} } } ])
db.users.aggregate( [ { $group:{_id:'$name', eta:{$push:'$age'} } } ])
db.users.aggregate( [ { $group:{_id:'$name', eta:{$addToSet:'$age'} } } ])
MongoDB
Aggregazione – Esempio
db.orders.aggregate( [ { $match: {status: 'A' } },
{ $group: {_id: '$cust_id',
total: { $sum: '$amount' }
}
} ] )
{ cust_id: 'A123',
amount: 500, status: 'A' }
$match
orders
results
{ cust_id: 'A123',
amount: 250, status: 'A' }
{ cust_id: 'B212',
amount: 200, status: 'A' }
{ cust_id: 'A123',
amount: 300, status: 'D' }
{ cust_id: 'A123',
amount: 500, status: 'A' }
{ cust_id: 'A123',
amount: 250, status: 'A' }
{ cust_id: 'B212',
amount: 200, status: 'A' }
$group{ _id: 'A123',
total: 750 }
{ _id: 'B212',
total: 200 }
MongoDB
Funzionalità Avanzate – MapReduce
In MongoDB è presente una implementazione interna del Map-Reduce per la
realizzazione di operazioni di aggregazioni complesse: si possono definire le operazioni
di map e di reduce creando delle funzioni in linguaggio JavaScript.
db.runCommand( { mapReduce: <collection>, map: <function>, reduce: <function>, finalize: <function>, out: <output>, query: <document>, sort: <document>, limit: <number>, scope: <document>, jsMode: <boolean>, verbose: <boolean> } )
opzionali
JavaScript function
MongoDB
Funzionalità Avanzate – MapReduce
db.orders.mapReduce(
function( ) { emit ( this.cust_id, this.amount ); },
function( key, values ) { return Array.sum( values ) },
{
query: { status: 'A' },
out: 'order_totals'
})
{ cust_id: 'A123',
amount: 500, status: 'A' }
query
orders
order_totals
{ cust_id: 'A123',
amount: 250, status: 'A' }
{ cust_id: 'B212',
amount: 200, status: 'A' }
{ cust_id: 'A123',
amount: 300, status: 'D' }
{ cust_id: 'A123',
amount: 500, status: 'A' }
{ cust_id: “A123”,
amount: 250, status: 'A' }
{ cust_id: “B212”,
amount: 200, status: 'A' }
{ _id: 'A123',
total: 750 }
{ _id: 'B212',
total: 200 }
{ 'A123': [500, 250] }
{ 'B212': 200 }
mapreduce
MongoDB
Funzionalità Avanzate – MapReduce
clientdefinisce una funzione di map, di reduce,
una query e una collection di output
1
2
mongosclientrequest
MongoDB
Funzionalità Avanzate – MapReduce
3
4
mongos
Config
MR request
Mongod: Primary
query
map
Shard N
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
Shard N
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
Shard N
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
MongoDB
Funzionalità Avanzate – MapReduce
5
5a
buffer
map <K,V>
<k,v><k,v>
buffer
<k,v> <k,v> <k,v> <k,v><k,v>partialreduce
Shard N
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
MongoDB
Funzionalità Avanzate – MapReduce
6
7
reduceMongodreduce
MongodreduceMongod
Shard N
Mongod: Primary
Mongod: Secondary
Mongod: SecondarymongosOut Collection Request
Shard N
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
Shard N
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
MongoDB
Funzionalità Avanzate – MapReduce
8
8a
reduceShard X
Mongod: Primary
Mongod: Secondary
Mongod: Secondary
Mongod: Primary finalize
MongoDB
Funzionalità Avanzate – MapReduce
Il Map Reduce implementato all'interno di Mongo presenta una serie di limiti:
- Javascript non è il linguaggio più indicato per il processamento di funzioni quali MapReduce
- Javascript limita l'utilizzo di librerie di terze parti per l'elaborazione dei dati
- Viene aggiunto un carico extra in termini di informazioni memorizzate
- Solo l'architettura con i shards consente di parallelizzare i dati e solo a seconda della query
che viene utilizzata
Quando i dati crescono occorre passare a un tool pensato per la gestione dei JOB MapReduce
MongoDB
Connettore Hadoop
Lo scopo di questo connettore è offrire la possibilità di usare MongoDB come sorgente
di input o destinazione di output per i task di MapReduce sotto Hadoop.
Permette di utilizzare nei tool dell'universo Hadoop, come Pig ed Hive, i documenti
BSON/MongoDB.
Generalmente il connettore MongoDB viene utilizzato come strato intermedio fra
l'applicazione e Hadoop in modo da sfruttare le potenzialità del query language di
MongoDB per filtrare i dati.
MongoDB
Connettore Hadoop – Aggregazione Batch
MongoDB
Connettore Hadoop – Data Warehouse
MongoDB
Connettore Hadoop – ETL
MongoDB
Connettore Hadoop – Casi d'uso
Gestione dati e metadati Analisi utenti
Gestione dati, check in,
review
Analisi utenti, segmentazione,
personalizzazione
Gestione dati hotel e
prezzi
Segmentazione hotel per
migliorare le ricerche
MongoDB
Connettore Hadoop – Casi d'uso
Gestione dati studenti Analisi studenti per
l'apprendimento mirato
Gestione datiModellazione rischio, sicurezza
e prevenzione truffe
Call center / Portali webAnalisi uso da parte degli
utenti e ottimizzazione
delle tariffe