Sei sulla pagina 1di 81

MongoDB

Database for Giant Ideas

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Agenda
Giorno 1
Mattina Pomeriggio
● Introduzione ai database NoSQL ● Sicurezza: autenticazione dei client,
● MongoDB: database agile per il web! autenticazione tra nodi del cluster, encryption
● Dev​ key features: modello a documenti, delle connessioni mediante SSL
relational vs document, JSON, BSON, MQL ● Creazione di utenti e ruoli per l’autenticazione
● (MongoDB Query Language), shell dei client
● Ops​ key features: pluggable architecture, storage ● Replica: principi e funzionamento
engines, replica, sharding ● Architetture di deploy di un replica set
● Mongo, mongod, mongos, mongodump, ● Esempio pratico di creazione di un replica set
mongorestore, mongoimport, mongoexport
● Installare MongoDB

DevOps
www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Agenda
Giorno 2
Mattina Pomeriggio
● Sharding: quando e perchè fare sharding ● Tipi di dato
● Componenti: shard, router (mongos), config servers (metadati) ● Chiavi e indici
● Shard keys: concetti e scelta della sharding key ● Operazioni CRUD da shell
● Tipi di shard keys: hashed e ranged ● Aggregation framework
● Shard tagging ● Ricerche testuali
● Use cases di un’architettura a shard: segmentazione dei dati ● Ricerche geospaziali
per posizione geografica, segmentazione per applicazione o
cliente, segmentazione basata sull’hardware
● Esempio pratico di creazione di un cluster a due shard

DevOps Dev
www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Agenda
Giorno 3
Mattina Pomeriggio
● Explain plan: esempio pratico di ottimizzazione ● ODM: Spring Data MongoDB e Morphia
di una query, index fit, working set ● GridFS
● Data design ● Data import su MongoDB: Apache NiFi
● Document validation ● Cenni all’integrazione con Apache Solr
● Pattern di struttura: relazioni 1 - 1, relazioni 1 - n, ● Cloud Manager: backup e monitoring sul cloud
alberi ● Cenni su Ops Manager e MongoDB Compass
● Timeseries ● Cenni su MongoDB Atlas
● Driver Java (sincrono e asincrono) ● MongoDB Enterprise vs MongoDB Community
● Concetti base di utilizzo del driver Java
(connessione a ReplicaSet e Shard)

Dev
www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Parte 1

Sharding

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Sviluppo con MongoDB
Applicazione

Driver

mongod

/data

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Replica Set con MongoDB
Applicazione

Driver

Secondary Primary Secondary

/data /data /data

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Replica Set con MongoDB
Limiti sulla RAM
del singolo server
Applicazione

Banda di rete Driver Limiti sulla CPU del


singolo server

Secondary Primary Secondary

Limiti sul Disk I/O

/data /data /data

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Componenti di un cluster
Applicazione

Driver

mongos mongos mongos

Secondary Primary Secondary Secondary Primary Secondary Secondary Primary Secondary

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Config server
Applicazione
Secondary Primary Secondary
Driver

mongos mongos mongos

Config Server

Secondary Primary Secondary Secondary Primary Secondary Secondary Primary Secondary

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Come si fa lo shard?
● Si crea il cluster

sh.addShard( "<replSetName>/s1-mongo1.example.net:27017")

sh.addShard( "s1-mongo1.example.net:27017") -> Nodo standalone, no in produzione!

● Si identifica una shard key per una collection


● Si abilita lo sharding nel database:

sh.enableSharding("<database>")

● Si esegue lo shard della collection:

sh.shardCollection("<database>.<collection>", { <key> : <direction> } )

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Shard Key
Determina la distribuzione dei documenti di una collection tra i nodi del cluster

● E’ unica per collection e non può essere cambiata una volta che è stata definita
● I valori della chiave di shard sono immutabili (non si possono fare update sui campi che la
compongono)
● E’ limitata a 512 bytes
● E’ usata per definire il routing delle query quindi è bene scegliere un campo da mettere
sempre nelle query
● Solo i valori della shard key sono unici tra tutti gli shard
● La Shard Key deve essere indicizzata (in caso di singolo campo) o essere il prefisso di un indice
composto (nel caso di più campi)
● I campi della Shard Key devono esistere in ogni documento della collection
● Non può essere un array

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Partizionamento

● L’utente definisce la Shard Key (x in questo caso)


● I valori della La Shard key definiscono un intervallo di dati
● Il Key Space è come l’insieme dei punti di una linea
● Un intervallo è un segmento di questa linea ed è chiamato Chunk

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Scelta della Shard Key

La scelta della Sharding Key dovrebbe ricadere su campi i cui valori siano uniformemente
distribuiti nello spazio di chiavi

Considerare comunque:

● cardinalità: determina il massimo numero di chunks che un balancer può creare. Infatti un valore
univoco della shard key può stare al più in un unico chunk in un determinato istante
● frequenza: rappresenta quanto frequente è un valore nello spazio di chiavi della Shard Key
● monotonicità: se la Shard Key è una funzione monotona crescente o decrescente, il bilanciamento
non sarà ottimale in quanto in scrittura sarà sempre caricato uno shard

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Cardinalità della Shard Key

{X:1} {X:2} {X:1}

minKey <= X < 1 1 <= X < 2 2 <= X < maxKey

Shard A Shard B Shard C

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Frequenza della Shard Key

{ X : 12 } { X : 12 } { X : 12 } { X : 23 }

minKey <= X < 10 10 <= X < 20 20 <= X < maxKey

Shard A Shard B Shard C

Possibile creazione di indivisible chunks

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Monotonicità della Shard Key

{ X : 25 } { X : 26 } { X : 27 }

minKey <= X < 10 10 <= X < 20 20 <= X < maxKey

Shard A Shard B Shard C

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Distribuzione dei dati

● Inizialmente esiste 1 solo chunk


● Ogni chunk determina un intervallo di valori della chiave di Shard
● La grandezza massima di default è 64MB
● MongoDB divide e migra automaticamente i chunk per uniformarne il numero tra i vari nodi di
shard

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Routing e balancing

● Le query, se utilizzano la shard key, sono


reindirizzate a uno shard specifico
● MongoDB bilancia il cluster (splitting)
● MongoDB migra i dati ai nuovi nodi (balancing)

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Auto Sharding

● Minimo sforzo richiesto


○ Trasparente per il client (quest’ultimo vede la stessa interfaccia di un
singolo mongod)
● Lo si configura in 2 passi
○ Abilitare lo sharding per il database
○ Abilitare lo shard di una collection all’interno del database

L’onere maggiore è probabilmente progettuale, ovvero nello scegliere la “migliore”


Sharding Key

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Cos’è uno Shard?
● Lo Shard è un nodo del cluster
● Lo Shard può essere un singolo mongod (non in produzione!) oppure un replica set
● Ogni database in un cluster ha sempre un Primary Shard. Questo nodo di Shard contiene
tutte le collection non “shardate” del database

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Metadati di un cluster

Vengono mantenuti sui cosiddetti Config Server

● Sono responsabili della memorizzazione degli intervalli di ognuno dei chunks e in quale shard
ognuno dei chunks risiede
● Può essere un nodo standalone (non in produzione!) o un replica set
● Non sono processi particolarmente “pesanti”, sono server di modeste dimensioni

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Instradamento delle richieste e gestione dei dati

In un’architettura a Shard l’applicativo deve sempre dialogare con un mongos

● Funziona come un router


● Non mantiene dati locali (sono già presenti nel database dei Config Server)
● Ne posso installare uno o più di uno
● E’ un processo “leggero”
● Si consiglia di installarlo nello stesso server dell’applicativo

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Esempio di infrastruttura di sharding

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Creiamo un cluster di esempio

In ambiente di sviluppo si può creare un cluster con un mongos, un nodo di shard e un config server

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Lanciare un config server

● mongod --configsvr
● Fa partire un Config Server sulla porta di default (27019)

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Lanciare un mongos

● mongos --configdb <hostname>:27019


● Fa partire un mongos sulla porta di default (27017)

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Creiamo lo shard

● mongod --shardsvr
● Fa partire un mongos sulla porta di default (27018)
● Lo shard non è ancora connesso al resto del cluster
● Lo shard potrebbe essere un nodo già in produzione

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Aggiungere lo Shard

● Loggarsi sul mongos: sh.addShard(‘<host>:27018’)


● Qualora fosse un replica set: sh.addShard(‘<rsname>/<seedlist>’)

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Verificare che lo Shard sia stato aggiunto

● Sempre dal mongos: sh.status()

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Bilanciamento del cluster
Il balancer è un processo che gira in background e monitora i chunks per Shard. Quando il numero
di chunks di uno Shard raggiunge le soglie di migrazione, il balancer tenta di migrare i chunks
automaticamente in modo da avere un uguale numero di chunks per Shard

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Acquisire il lock del Balancer

Il processo balancer, dalla versione 3.4 di MongoDB, risiede nel nodo Primary del replica set dei
Config Server. Nelle versioni precedenti di MongoDB risiedeva sul mongos.

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Spostare i chunks
● Mongos invia il comando di spostamento dei chunk (moveChunk) allo shard
● Lo shard sorgente notifica la necessità di spostamento di un chunk allo shard di destinazione
● Lo shard di destinazione avvia il processo di acquisizione dei dati dalla sorgente

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Commit della migrazione
● Quando il processo di migrazione è terminato lo shard comunica l’esito al config Server:
○ comunica la posizione dei nuovi chunk

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Cleanup
● Lo shard sorgente cancella i dati
● Mongos rimuove il lock dal balancer dopo che l’operazione di rimozione dei chunk è stata
completata.

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Routing delle query

● Targeted query
● Scatter Gather Queries
● Scatter Gather Queries with Sort

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Targeted query

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Non targeted query

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Non targeted query con sorting

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Hashed Sharding
La chiave di Shard è formata da un singolo campo su cui viene creato un indice hashed. L’obiettivo è
quello di creare una distribuzione uniforme sull’intero spazio delle chiavi della chiave di Shard

Indicato se le query sono in uguaglianza

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Ranged Sharding
E’ lo sharding di default. E’ particolarmente efficiente quando:
● la Shard Key ha un’alta cardinalità
● la Shard Key ha una bassa frequenza
● la Shard Key non è monotona crescente o decrescente

Indicato sia per query in uguaglianza che


per query in range

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Shard Tagging*
Permette di associare uno o più range di valori della shard key a dei gruppi di shards (detti zones) in
modo da controllare la distribuzione dei dati nel cluster

● Un nodo di Shard può


appartenere a più zone
(es. Beta appartiene alla
zona A e B)
● Una zona può avere più
nodi di Shard (es. la zona
A contiene Alpha e Beta)

*In MogoDB 3.4 il concetto di Shard Tagging è stato ribattezzato in “Zones”

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Bilanciamento con lo Shard Tagging
Quando un chunk viene marcato come “da migrare” il balancer verifica, in funzione del range di
appartenenza, quali siano le zones dove può essere migrato (ad es. se appartiene al range {X: 1,
X:10} allora può essere migrato in uno degli Shard della zona A, ovvero Alpha o Beta).

I chunks che non ricadono in una zone possono essere distribuiti in uno “qualsiasi” degli
shards e subire un “normale” bilanciamento tra di essi

Se il balancer, nel monitorare la distribuzione dei chunks si accorge che uno o più chunk non
rispetta le zone configurate rispetto allo shard in cui si trova, il balancer migra quel/i chunk/s su uno
shard coerente con la zone a cui appartiene (es. zone DAILY e ARCHIVE in funzione di uno sharding
sulla data d’inserimento per cui ogni sera viene aggiornato il range della zona DAILY e
automaticamente i dati del giorno precedente vengono migrati sulla zona ARCHIVE)

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Shard Tagging use cases

● Isolare uno specifico sottoinsieme di dati in uno specifico insieme di nodi


di shard (es. hot data e cold data, cliente A su shard A e cliente B su
shard B)
● Far sì che i dati più rilevanti risiedano su shards geograficamente vicini
agli application servers
● Indirizzare il traffico verso determinati shards in funzione
dell’hardware/performance degli shards stessi

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Gestire le Zones
Aggiungere uno shard ad una zona (connettersi al mongos)
sh.addShardToZone("Alpha", "A")
sh.addShardToZone("Beta", "A")
sh.addShardToZone("Beta", "B")

Associare un range ad una zona (connettersi a mongos)


sh.updateZoneKeyRange(
"exampledb.collection", Un range può essere assegnato ad una sola zona
{ a : 1 },
{ a : 10 },
"Alpha"
)

Rimuovere un range da una zona (connettersi al mongos)


sh.removeRangeFromZone("exampledb.collection", {a: 1}, {a: 10})

Verificare le zone associate ad uno shard (connettersi al mongos)


sh.status()

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Zones: segmentazione per applicazione o cliente
Shard key: { client : 1, userid : 1 }

Architettura Zone
Fonte: https://docs.mongodb.com/manual/tutorial/sharding-segmenting-shards/

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Zones: segmentazione diversi SLA o SLO - 1 di 2

Una applicazione di sharing delle foto vuole dare accesso veloce alle foto caricate negli ultimi 6 mesi

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Zones: segmentazione diversi SLA o SLO - 2 di 2

Shard key: { creation_date : 1 }

Architettura Zone

Ogni giorno un job schedulato modifica il range della zona “recent” e quindi tutti i documenti più vecchi di
6 mesi vengono automaticamente spostati dal balancer nella zona “archive”
www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Backup di un cluster in Sharding - 1 di 2

Per effettuare un backup point-in-time di un cluster in shard bisogna


fermare le scritture. Se le scritture non si possono fermare (sistemi di
produzione) si può ottenere un’approssimazione di un point-in-time backup

File System Snapshot Database Dump

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Backup di un cluster in Sharding - 2 di 2
1. Disabilitare il balancer
2. Effettuare il lock di un secondary in ogni replica set del cluster (sia dei
config che dei replicaset degli shard)*
3. Effettuare il backup di un config server
4. Rilasciare il lock sul secondary del replica set dei config server*
5. Effettuare il backup del nodo secondary per ognuno degli shard
6. Rilasciare il lock sul secondary di ognuno dei replica set dei nodi di shard*
7. Riabilitare il balancer
Fonti:
● https://docs.mongodb.com/manual/tutorial/backup-sharded-cluster-with-database-dumps/
● https://docs.mongodb.com/manual/tutorial/backup-sharded-cluster-with-filesystem-snapshots/

* non necessari in caso di File System Snapshot con journal abilitato e presente nello stesso volume dei dati

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Parte 2

Lab: creazione di un
cluster con due shard

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Parte 3

Chiavi e indici

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Indici

Un indice è una struttura dati che permette la localizzazione rapida delle


informazioni relative al campo su cui è costruito e riveste una parte
fondamentale in fase di ottimizzazione delle query.

● MongoDB permette di definire gli indici a livello di collection (max 64 per collection)
● Gli indici si possono definire su qualsiasi campo o campo di documento embedded
● MongoDB crea in automatico uno unique index sul campo _id che deve essere presente in
ogni documento. L’indice sul campo _id non può essere cancellato.
● Sono strutture dati (B-Tree) ordinate

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
ObjectId

E’ uno dei tipi BSON utilizzati spesso per il campo _id

12 bytes

0 1 2 3 4 5 6 7 8 9 10 11

Timestamp Machine PID Increment

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Funzionamento

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Creazione di un indice

db.collection.createIndex( <key and index type specification>, <options> )

Esempio:
> db.users.createIndex( { username : 1 } )
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
>

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Opzioni di un indice

● background: crea un indice in background evitando così il lock del database durante la
creazione
● unique: tutti i valori dell’indice nella collection sono univoci
● name: permette di specificare un nome all’indice altrimenti viene generato automaticamente
● sparse: indicizza tutti e soli i documenti che hanno i campi dell’indice (anche se null). Questi tipi
di indice permettono un uso inferiore di risorse ma devono essere usati con cautela perchè
potrebbero non tornare tutti i documenti della collection
● expireAfterSeconds: vengono definiti indici TTL perché permettono la rimozione dei
documenti indicizzati dopo un tempo specificato come parametro. Se non si indicizza un
campo Date (o un array di Date) i documenti non vengono eliminati così come se un
documento non possiede il campo indicizzato
● partialFilterExpression: vengono definiti Partial Index e sono un superset degli sparse. In
pratica alla creazione dell’indice si specifica una condizione di “filtraggio” delle entry dell’indice.
Vengono indicizzati solo i documenti che soddisfano la clausola di filtro

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Altre operazioni con gli indici

Cancellazione di un indice
db.users.dropIndex({ “username” : 1 })

Visualizzazione degli indici di una collection


db.users.getIndexes()

Statistiche degli indici di una collection


db.users.stats()

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Tipi di indici

Single field Compound Multikey

Text GEO Hashed

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Single field

Gli indici single field possono essere creati anche su campi di documenti embedded
Vengono usati anche per le operazioni di sort (anche in ordine inverso)

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Compound

Vengono usati anche per le operazioni di sort ma solo in determinate condizioni

Vengono usati anche in caso la clausola di filtro costituisca prefisso dell’indice

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Multikey

Un indice compound e multikey può avere un solo campo di tipo array indicizzato
Non sono utilizzabili come chiave di Shard

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Text

Supportano ricerche testuali all’interno di stringhe o di array di stringhe

db.reviews.createIndex( { comments: "text" }


)
db.reviews.createIndex( { “$**”: "text" } ) Indicizza ogni campo stringa di ogni documento

Gli indici testuali generano una chiave per ogni parola univoca in ognuno dei campi indicizzati
(può essere composto) per ognuno dei documenti della collection

Gli indici testuali sono sparsi per default


Una collection può avere al più un indice testuale

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
GEO

● Permettono le query geospaziali su una sfera


● Supportano i dati salvati come oggetti GeoJSON (http://geojson.org/) oppure in formato legacy
coordinate

<field>: { type: <GeoJSON type> , coordinates: <coordinates> } <field>: [<longitude>, <latitude> ] oppure
<field>: { <field1>: <longitude>, <field2>: <latitude> }
Es.
Es.
location: {
type: "Point", location: [-73.856077, 40.848447] oppure
coordinates: [-73.856077, 40.848447] location: {
} longitude: -73.856077,
latitude: 40.848447
}

Principali operatori: $near, $geoWithin, $geoIntersects

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Parte 4

Aggregation framework

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Cos’è?

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Come funziona

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Principali operatori

● $project
● $match
● $limit
● $skip
● $unwind
● $group
● $sort
● $lookup
● $out
● $count

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Altri operatori
● $sortByCount
● $addFields
● $replaceRoot
● $graphLookup
● $sample
● $collStats
● $redact
● $geoNear
● $indexStats
● $facet
● $bucket
● $bucketAuto
www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
MongoDB aggregation VS SQL aggregation
SQL MongoDB aggregation framework
WHERE $match

GROUP BY $group

HAVING $match

SELECT $project

ORDER BY $sort

LIMIT $limit

SUM() $sum

COUNT() $count

join $lookup

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
$project - 1 di 3
● include, esclude o rinomina i campi
● permette di aggiungere nuovi campi
● permette di creare campi su sub-documenti

Il campo “_id” è sempre visibile di default, qualunque sia la project


{
“_id”: 1,
db.test.aggregate( [ { $project : {nome: 1 , cognome: 1 } } ] ) “nome”: “giorgio”,
“cognome”: “rossi”
}

{
db.test.aggregate( [ { $project : { _id: 0, name: 1 , surname: 1 } } ] ) “nome”: “giorgio”,
“cognome”: “rossi”
}

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
$project - 2 di 3

{ { “$project”: {
"_id" : 271466, “_id”: 0,
"amenity" : "pub", “amenity”: 1,
"name" : "The Red Lion", “name”: 1,
"location" : { }}
"type" : "Point",
"coordinates" : [
-1.5494749,
50.7837119
]
} {
} “amenity” : “pub”,
“name” : “The Red Lion”
}

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
$project - 3 di 3
{ “$project”: {
{ “_id”: 0,
"_id" : 271466, “name”: 1,
"amenity" : "pub", “meta”: {
"name" : "The Red Lion", “type”: “$amenity”
"location" : { }
"type" : "Point", }}
"coordinates" : [
-1.5494749,
50.7837119
]
}
} {
“name” : “The Red Lion”
“meta” : {
“type” : “pub”
}}
www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
$match - 1 di 2

● filtra i documenti
● si usa la stessa sintassi delle query
● se si usa $text deve essere il primo nella pipeline
● è bene usarlo il prima possibile nella pipeline per evitare sprechi di
risorse
● se posizionato all’inizio della pipeline può sfruttare gli indici
● non è possibile usare $where

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
$match - 2 di 2
{ { "$match": {
"_id" : 271421,
"amenity" : "pub",
"name": "The Red Lion"
"name" : "Sir Walter Tyrrell", }}
"location" : {
"type" : "Point",
"coordinates" : [
-1.6192422,
50.9131996
]
}
}

{ {
"_id" : 271466, "_id" : 271466,
"amenity" : "pub", "amenity" : "pub",
"name" : "The Red Lion", "name" : "The Red Lion",
"location" : { "location" : {
"type" : "Point", "type" : "Point",
"coordinates" : [ "coordinates" : [
-1.5494749, -1.5494749,
50.7837119 50.7837119
] ]
} }
} }

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
$group - 1 di 2

● raggruppa i documenti per ID (campo _id obbligatorio). Mettendo


null come valore del campo _id, viene applicato l’operatore di group
sull’intero dataset (ad es. “sommare il valore su tutta la collection”)
● si usa con altri operatori (accumulatori: $sum, $avg, $first, $last,
$max, $min, ecc.) che permettono di calcolare nuovi campi
● i documenti vengono processati in memoria

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
$group - 2 di 2

{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }

Obbligatorio. Specificare
null per applicare gli
accumulatori su tutti i
documenti

Opzionale

$max, $min, $avg, $sum


$addToSet, $push, $first, $last

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Limiti

● I documenti risultato della pipe di aggregazione devono sottostare ai


limiti del documento BSON (16MB). Durante la pipeline i documenti
possono eccedere questa dimensione massima
● Ogni stage della pipeline di aggregation ha un limite d’uso della memoria
pari a 100MB. Per bypassare questo limite si può usare “allowDiskUse”
tranne che per $graphLookup

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Query di ricerca full text
● Deve esserci un indice “text” creato sui campi di ricerca (ogni collection
ne supporta al più uno ma anche costruito su più campi, quindi
composto)
● L’operatore $text scompone la stringa di ricerca in token usando come
separatore lo spazio e la punteggiatura ed esegue una ricerca di tutti i
token in OR: db.stores.find( { $text: { $search: "java coffee shop" } } )
● Si può cercare anche per un intera stringa facendo in modo che non
venga separata in token ricercabili singolarmente:
db.stores.find( { $text: { $search: "java \"coffee shop\"" } } )
● Si possono escludere dei termini dalla ricerca (tutti i documenti che
contengono le parole java e coffee ma non shop):
db.stores.find( { $text: { $search: "java shop -coffee" } } )

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
Query di ricerca geospaziali
● Non può essere usato un indice geospaziale come sharding key
● Si può comunque definire un indice geospaziale in una collection
shardata purché su un campo diverso dalla sharding key (problema delle
scatter gather query)
● Nelle collection shardate non si possono usare gli operatori $near e
$nearSphere
● Usate sempre indici 2dsphere per query “sferiche”. L’indice 2d potrebbe
dare risultati poco accurati
● E’ possibile effettuare aggregazioni usando lo stage $geoNear
dell’Aggregation Framework

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter
GRAZIE!

www.zero12.it Nome
Nome Cognome
Roberto
ciao
Cognome
Contiero
www.zero12.it @account Twitter
@account
@contieroroberto
Twitter

Potrebbero piacerti anche