MongoDB
Poccia Silvestro, Trevisani Luca
11 gennaio 2011
Abstract
Nel presente documento si presenta MongoDB, una relativamente nuova tecnologia per l’implementazione di un DBMS document-oriented.
Il testo nasce dalla curiosità di approfondire un approccio completamente
senza schemi, molto lontano dalle classiche implementazioni relazionali che
negli anni ci hanno rassicurato con le loro ben definite strutture ma allo stesso tempo imbrigliato in logiche rigide, difficilmente alterabili dopo la fase di
progetto.
Il nostro documento si articola in tre capitoli fondamentali:
1. Panorama Tecnologico. In questo capitolo si analizza a volo d’uccello il panorama odierno in merito alle tecnologie impiegate per la realizzazione dei
DBMS moderni. In particolare si elencano e discutono le caratteristiche
peculiari degli approcci relazionali ed ad oggetti.
2. MongoDB. In questo capitolo si presenta il modello document-oriented
relativo al MongoDB, per poi introdurre ulteriori scelte architetturali e
funzionalità proprie del MongoDB.
3. MongoDB HowTo. In questo capitolo si presentano le principali operazioni effettuabili sul DBMS attraverso le interfacce messe a disposizione da
MongoDB, con un approccio pratico, a supporto di un eventuale utilizzo
del sistema da parte di un nuovo utente.
4. Conclusioni. Nel capitolo conclusivo si tirano le somme di un eventuale
impiego di MongoDB in un sistema reale.
Ad integrare il testo due appendici illustrano sinteticamente l’impiego della
sintassi JSON per interagire con il sistema e le principali differenze e similitudini
con il linguaggio SQL ed il database relazionale MySQL.
Indice
Elenco delle figure
iii
Elenco delle tabelle
v
1 Panorama Tecnologico
1.1 RDBMS . . . . . . .
1.2 ODBMS . . . . . . .
1.3 OODBMS . . . . . .
1.4 ORDBMS . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
2
3
5
7
2 MongoDB
2.1 Document-oriented storage
2.2 Supporto completo Indici .
2.3 Replication . . . . . . . . .
2.4 Auto-Sharding . . . . . . .
2.5 Querying . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
9
11
12
12
14
3 MongoDB HowTo
3.1 Installazione . . . . . . . . . . . . . . . . . . .
3.1.1 Utilizzo avanzato del demone mongod
3.2 Gestione Database . . . . . . . . . . . . . . .
3.2.1 Selezione del database . . . . . . . . .
3.2.2 Creazione del database . . . . . . . . .
3.2.3 Eliminazione del database . . . . . . .
3.3 Gestione Utenti . . . . . . . . . . . . . . . . .
3.3.1 Creazione Utente . . . . . . . . . . . .
3.3.2 Modifica Utente . . . . . . . . . . . .
3.3.3 Eliminazione Utente . . . . . . . . . .
3.3.4 Autenticazione Utente . . . . . . . . .
3.4 Gestione Collezioni . . . . . . . . . . . . . . .
3.4.1 Creazione Collezione . . . . . . . . . .
3.4.2 Creazione Oggetto . . . . . . . . . . .
3.4.3 Modifica Oggetto . . . . . . . . . . . .
3.4.4 Eliminazione Oggetto . . . . . . . . .
3.4.5 Eliminazione Collezione . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
15
15
16
17
18
18
18
20
20
20
20
21
24
25
25
26
28
29
.
.
.
.
.
.
.
.
.
.
.
.
4 Conclusioni
31
i
ii
INDICE
5 Appendice
33
5.A Sintassi JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.B Migrare da SQL a MongoDB . . . . . . . . . . . . . . . . . . . . 35
Bibliografia
37
Elenco delle figure
1.1
Tecnologie OODBMS . . . . . . . . . . . . . . . . . . . . . . . . .
7
3.1
3.2
Avvio demone mongod . . . . . . . . . . . . . . . . . . . . . . . .
Avvio della shell mongo . . . . . . . . . . . . . . . . . . . . . . .
15
16
iii
Elenco delle tabelle
3.1
Tabella delle opzioni di modifica . . . . . . . . . . . . . . . . . .
27
5.1
5.2
Tabella tecnica SQL MongoDB . . . . . . . . . . . . . . . . . . .
Tabella comparativa SQL-MongoDB . . . . . . . . . . . . . . . .
35
36
v
Capitolo 1
Panorama Tecnologico
Di necessità virtù è forse l’espressione che meglio riassume i contenuti di
questa introduzione, perchè si tratterà l’evoluzione dei DBMS - Database Management System - dagli RDBMS - Relational DBMS - agli ODBMS - Object
DBMS. Cosa hanno in comune? Perchè sono nati?
In sostanza alla base di un’evoluzione c’è sempre una necessità.
Grazie allo sviluppo di internet, i database oggi sono usati più che mai per
memorizzare ed accedere alle informazioni in contesti sempre più dinamici e con
una forte esigenza di interoperabilità tra sistemi, devono quindi:
ˆ permettere alle applicazioni di mutare ed evolvere velocemente.
ˆ consentire alle applicazioni di essere conformi ai nuovi standard de facto
o de iure.
ˆ garantire in ogni caso i capisaldi delle proprietà ACID.
Questo ha dato una forte spinta allo sviluppo di tecnologie per i database.
Il panorama odierno è dominato da tre classi principali e le zone grigie che le
dividono:
ˆ Relazionale
ˆ Object-Oriented
ˆ Object-Relational
In questa introduzione ci occuperemo di discutere questi tre modelli evidenziandone i punti di forza ed i loro talloni d’Achille. Nel capitolo successivo si
tratterà un ulteriore modello: il Document-Oriented dbms, che esalta le necessità di performance e polimorfismo delle applicazioni di nuova generazione, dove
l’utente - non più strettamente vincolato dal sistema - riveste un ruolo centrale
nella creazione e gestione dei dati (tipico nel paradigma del web 2.0) e fornisce
supporto alle problematiche attuali di labeling delle risorse (fondamentale per
il web 3.0 in arrivo).
1
2
CAPITOLO 1. PANORAMA TECNOLOGICO
1.1
RDBMS
Si deve ad Edgar F. Codd negli oramai lontani anni 70 la nascita dei database relazionali ; il primo prototipo fu sviluppato da IBM in collaborazione con
l’Università di Berkley; vari vendors poterono cosı̀ offrire database relazionali, costruendo la rete di database relazionali che già si prestavano al supporto di
applicativi complessi e per i quali era richiesta una certa affidabilità e consistenza
dei dati, come quelli di ambito finanziario.
Un database è un archivio strutturato in modo tale da consentire l’accesso
e la gestione dei dati stessi (l’inserimento, la ricerca, la cancellazione ed il loro
aggiornamento) da parte di particolari applicazioni software ad essi dedicate.
Il database è un insieme di informazioni, di dati che vengono suddivisi per
argomenti in ordine logico (tabelle) e poi tali argomenti vengono suddivisi per
categorie (campi). Le tabelle, in un RDBMS, sono collegate fra loro da relazioni.
L’uso della teoria degli insiemi consente di strutturare i dati in serie di tabelle
composte da colonne (domini).
ˆ ogni colonna corrisponde a un attributo di quella relazione
ˆ ogni riga corrisponde a un record che contiene i dati valorizzati per un
entità (tupla).
Gli RDBMS si basano sui 3 elementi cardini - secondo Ted Codd - per
un sistema relazionale: il concetto di relazionale, l’integrità e la normalizzazione. Inoltre è previsto uno standard per l’interrogazione della base dati: SQL Standard Query Language.
Lo sviluppo rapidissimo del database relazionale è strettamente legato alle
applicazioni per le quali tale modello ha fatto da padrone ovvero quelle finanziarie–bancarie, dove i tipi di dato semplici ed una forte strutturazione delle
tabelle in binari vincolanti ben si sposavano con le caratteristiche del modello.
Nelle applicazioni d’oggi questa eccessiva rigidità che negli albori del modello
rappresentava una caratteristica rassicurante è diventato - in taluni casi - un
pesante fardello, se non un vero e proprio limite: pensiamo ad un blog, ci basta
gestire dati semplici?
ˆ
ˆ
ˆ
ˆ
stringhe
numeri
valori booleani
date
Caratteristica dei blog è che l’utente al centro del processo creativo: mostra se
stesso e la propria personalità.
Come è possibile fornire in un db relazionale la flessibilità a ciascuna persona
per creare contenuti completamente diversi da post a post, siano essi semplici o
complessi, più o meno articolati ?
Certo un database relazionale ha molti vantaggi:
ˆ il sistema è semplice, flessibile e produttivo, poichè le tabelle sono semplici,
i dati sono semplici per cui facili da capire e da comunicare con gli altri.
ˆ l’SQL è un linguaggio facile da imparare e soprattutto è uno standard.
1.2. ODBMS
3
I database relazionali hanno però dei limiti, come già affermato, gestiscono
solo dati semplici per cui si prestano male alla gestire dati complessi, strutturati
al di fuori degli schemi o con un alto tasso evolutivo. Ma questo non basta, un
altro limite dei database relazionali è l’inadeguatezza ad operare con linguaggi
al di fuori di SQL.
Dopo lo sviluppo iniziale degli RDBMS, sono nate applicazioni - scritte maggiormente in c++ e javascript - basate su RDBMS, per le quali era comunque
necessario passare per SQL per ottenere i dati e poi trasportarli all’interno degli
oggetti dell’applicativo.
Questo mismatch lascia un pesante gap tra linguaggio applicativo ed il
DBMS relazionale, per cui i database relazionali non funzionano in modo efficiente con questi linguaggi, questo è accettato per aumentare l’astrazione
(portabilità).
Altro limite è l’esigenza che le informazioni debbano essere in tabelle in cui
le relazioni tra entità siano realizzate usando dei valori (vincoli di integrità
referenziali, che introducono una complessità strutturale maggiore).
Oggi, il modello relazionale è il modello delle basi di dati dominante cosı̀ come
la base per i prodotti di punta DBMS.
1.2
ODBMS
Sebbene gli RDBMS siano ormai insostituibili nell’ambito delle applicazioni
finanziarie, in altri ambiti si sono sviluppati dei modelli più flessibili capaci di
gestire dati complessi: gli ODBMS - Object DBMS.
I sistemi classici relazionali hanno consentito di realizzare ottimi sistemi
gestionali (banche e finanza) caratterizzati da persistenza, condivisione ed affidabilità. Per questi sistemi bastava gestire dati semplici (stringhe, caratteri,
numeri).
I sistemi relazionali permettevano con la loro sintassi di realizzare query
anche molto complesse.
Causa la rapida evoluzione tecnica, sono nate delle aree applicative per cui
gli RDBMS non erano propriamente adatti. Basti pensare all’archiviazione di
immagini, volendo usare un RDBMS le alternative sarebbero:
ˆ inserire in un campo di una tabella il path dell’immagine.
ˆ valorizzare un campo col corrispettivo binario dell’immagine.
Se questo è il problema che si ritrova per un’immagine pensiamo a quanto cresce
in scala se ci occupiamo di
ˆ archiviazione di foto
ˆ gestione di codici parlanti
ˆ videosorveglianza
oppure in generale di applicazioni che nella maggior parte dei casi necessitano
di gestire dati a struttura complessa.
4
CAPITOLO 1. PANORAMA TECNOLOGICO
Se poi si tratta di applicazioni dove l’utente deve poter gestire tipi predefiniti
e tipi definiti dall’utente stesso in un approccio dove l’utente diventa centrale
nell’applicazione, risulta evidente che l’utilizzo di un RDBMS non sia ottimale.
Tutti questi sistemi hanno una caratteristica in comune: tutte le unità fondamentali sono oggetti. Gli oggetti nel paradigma relazionale sono splittati su
molte tabelle, pertanto il divario tra oggetto e struttura relazionale è riempito
da query molto complesse. L’utilizzo di un paradigma che coinvolga oggetti può
risolvere problemi come:
ˆ la specifica di strutture complesse con relazioni unitarie tra i dati.
ˆ la descrizione dei dati integrata e le operazioni per il loro recupero.
ˆ Un rapporto 1:1 con i linguaggi di programmazione ad oggetti.
Una base di dati ad oggetti è una collezione di oggetti in cui ogni oggetto
ha un identificatore, uno stato ed un comportamento.
ˆ Stato: insieme dei valori assunti dalle proprietà dell’oggetto.
ˆ Comportamento: insieme dei metodi che possono essere applicati all’oggetto.
ˆ OID: identificativo dell’oggetto (in genere non è gestito dall’utente ma gli
è invisibile).
Nel paradigma ad oggetti ci sono due approcci che, sebbene presentino delle
caratteristiche comuni, si presentano rispetto agli schemi relazionali in maniera
dissimile:
ˆ OODBMS - Object-oriented DBMS
ˆ ORDBMS - Object-relational DBMS
Nel paradigma ODBMS un oggetto è un’istanza di un certo tipo.
Un tipo definisce le proprietà statiche (attributi) e dinamiche (metodi) dell’oggetto. La complessità strutturale che questo modello offre è garantita proprio dall’uso di costruttori di tipo. Pertanto oggetti che nel mondo reale sono
complessi vengono rimarcati dalla strutturazione di un tipo complesso.
Una classe è un raccoglitore di oggetti dello stesso tipo. In genere la definizione di una classe si articola in due passi:
ˆ Interfaccia
ˆ Implementazione
Alla base di un approccio orientato agli oggetti c’è il principio di incapsulamento: l’interfaccia descrive solo le operazioni applicabili sull’oggetto mentre
l’implementazione nasconde la struttura dati e il codice interno ai metodi.
La persistenza in questi sistemi è una caratteristica trasparente al programmatore.
1.3. OODBMS
1.3
5
OODBMS
Gli OODBMS estendono i DBMS a partire dalle caratteristiche dei linguaggi di
programmazione ad oggetti, pertanto superano il disadattamento di impedenza che esiste nelle basi di dati relazionali tra i linguaggi in cui sono scritte le
applicazioni e l’SQL con cui sono scritte le query per il recupero degli oggetti.
Già dai primi anni ’80 per combattere le limitazioni del RDBMS e affrontare
la sfida della crescita crescente di Internet e il Web, i programmatori hanno
sviluppato database object-oriented.
L’obiettivo principale degli Object-Oriented Database Management System,
sinteticamente noti come OODBMS, è quello di fornire dati coerenti, indipendenti, sicuri, controllati e servizi estensibili di gestione dati per sostenere il
modello orientato agli oggetti.
Tra le caratteristiche fondamentali dei database o-o, l’unione di programmazione object-oriented con tecnologia del database fornisce un sistema integrato di
sviluppo di applicazioni, portando in questo modello principi distintivi della programmazione orientata agli oggetti: eredità, incapsulamento dei dati, identità
dell’oggetto e polimorfismo.
L’ereditarietà permette di sviluppare soluzioni a problemi complessi in modo incrementale attraverso la definizione di nuovi oggetti in termini di oggetti
precedentemente definiti.
L’incapsulamento dei dati permette di nascondere lo stato interno degli
oggetti. Gli oggetti incapsulati sono quegli oggetti che possono essere valutati solo utilizzando i loro metodi, invece di accedere direttamente ai loro stati
interni. Per realizzare l’incapsulamento bisogna riferirsi alle parti pubbliche e
private di una classe.
Parti private sono gli stati interni della classe che appartengono alla classe
e non possono essere acceduti direttamente dall’esterno.
Parti pubbliche sono i comportamenti, i metodi, che facendo parte di una
classe hanno visibilità degli attributi della stessa e quindi possono accedervi in
lettura e scrittura, permettendo cosı̀ di esporre in maniera controllata lo stato
interno agli altri oggetti dell’ambiente.
L’identità dell’oggetto permette agli oggetti del database di essere indipendenti l’uno dall’altro.
Il Polimorfismo ed il binding dinamico permettono di definire le operazioni per un oggetto e poi di condividere la specifica della cooperazione con altri
oggetti. Questo permette agli utenti e/o programmatori di comporre oggetti,
di fornire soluzioni senza dover riscrivere il codice comune a più classi. Un linguaggio per OODBMS si compone di una parte per la definizione dei dati ed
un’altra per la manipolazione del linguaggio (DDML = odl + oql). L’uso di
questo linguaggio permette di creare dati persistenti, aggiornarli, cancellarli e
6
CAPITOLO 1. PANORAMA TECNOLOGICO
recuperarli. Un OODBMS ha insito un vantaggio computazionale rispetto a un
database relazionale, perché evita il disadattamento (mismatch) di impedenza.
Il DDML - Document Definition Markup Language - permette agli utenti di
definire una base di dati, inclusa la creazione, modifica ed eliminazione di oggetti
e di stabilirne le relazioni. Inoltre i linguaggi DDML vengono utilizzati per
effettuare operazioni di mantenimento e di interrogazione di un database, cioè,
operazioni come l’aggiornamento, l’inserimento, la modifica e l’interrogazione
dei dati.
Gli OODBMS presentano molti vantaggi:
ˆ sono orientati agli oggetti pertanto permettono di rappresentare la realtà
il modo più naturale.
ˆ le operazioni definite su questi tipi di sistemi non dipendono dalla particolare applicazione di database che è in esecuzione in un dato momento.
ˆ i tipi di dati trattati dai database orientati agli oggetti possono essere
estesi per supportare dati complessi.
ˆ derivati dall’object-oriented sono la riusabilità, la stabilità e l’affidabilità.
ˆ le relazioni sono rappresentate in modo esplicito, spesso sostenendo sia
l’accesso alla navigazione che l’accesso associativo alle informazioni. Questo si traduce in un miglioramento delle prestazioni di accesso ai dati
rispetto al modello relazionale a scapito comunque della manutenibilità.
ˆ gli utenti sono autorizzati a definire i propri metodi di accesso ai dati e
come i dati saranno rappresentati e/o manipolati in maniera flessibile.
Lo svantaggio maggiore degli OODBMS
di dati.
è che manca un modello comune
La tecnologia dei database object-oriented è un matrimonio di programmazione orientata agli oggetti e tecnologie di database, la figura 1.1 mostra come
questi concetti di programmazione e di database si siano uniti per offrire ciò che
oggi chiamiamo i database object-oriented.
Tutte queste funzionalità si uniscono sinergicamente a fornire significativi
vantaggi di produttività per gli sviluppatori di applicazioni basate su database.
Quando la complessità delle interrelazioni tra le informazioni all’interno del
database aumenta, cosı̀ fanno anche i vantaggi che si ricavano dal rappresentare
le relazioni in modo esplicito.
Un altro vantaggio di rappresentare relazioni in modo esplicito è il miglioramento delle prestazioni di accesso ai dati in confronto ai database relazionali
che basano tutto sul valore.
Una caratteristica unica degli oggetti è che hanno un’identità che è indipendente dallo stato dell’oggetto. Per esempio, su un oggetto macchina possiamo
rimodellare la macchina e cambiare il suo aspetto, il motore, la trasmissione, e
le gomme in modo che appaia completamente diverso, sebbene venga comunque
riconosciuto come lo stesso oggetto che avevamo inizialmente.
L’Object-identità consente agli oggetti di essere condivisi su di un sistema
distribuito.
1.4. ORDBMS
7
Figura 1.1: Tecnologie OODBMS
Tutti questi vantaggi applicativi rendono i database object-oriented preferibili per supportare problemi di gestione delle informazioni, caratterizzati dalla
necessità di gestire:
ˆ un gran numero di tipi di dati diversi,
ˆ un gran numero di relazioni tra gli oggetti,
ˆ oggetti con comportamenti complessi.
Le aree applicative dove questo tipo di complessità esiste comprendono l’ingegneria, la fabbricazione, le simulazioni, l’office automation.
1.4
ORDBMS
Gli ORDBMS - Object-Relational Database Management System - sono sistemi
il cui punto focale è “il tentativo di estendere i sistemi di database relazionali con
le funzionalità necessarie per supportare una classe più ampia di applicazioni e,
in molti modi, fornire un ponte tra i paradigmi relazionali e object-oriented”.
Gli ORDBMS sono stati creati per gestire nuovi tipi di dati complessi in
risposta al paradigma OODBMS, di fatto il loro sviluppo fu spinto dal maggiore
utilizzo dei linguaggi di programmazione object-oriented per la gestione dei dati
complessi.
Il vantaggio fondamentale dei sistemi ORDBMS è permettere alle aziende di
continuare a utilizzare i sistemi esistenti, senza dover fare grandi cambiamenti,
8
CAPITOLO 1. PANORAMA TECNOLOGICO
proponedosi come una estensione – naturale evoluzione – dei database relazionali. Un secondo vantaggio è che permettono agli utenti e programmatori di
iniziare a utilizzare sistemi orientati agli oggetti in parallelo all’utilizzo dei db
relazionali.
Il modello dei dati offerto dagli ORDBMS è compatibile col modello dei dati
relazionali, cosı̀ da consentire la definizione di tabelle e vincoli di integrità SQL.
Ad ogni modo è suggerito utilizzare un approccio diverso tramite la definizione di tipi cosı̀ da avere un maggiore riutilizzo delle strutture create col
meccanismo delle gerarchie. L’uso di costruttori complessi rimarca una prima
sostanziale differenza dai database relazionali classici. I tipi possono essere:
ˆ tipi distinti: corrispondono ai domini di SQL.
ˆ tipi strutturati: sono usati per creare le strutture delle tuple da inserire
nelle tabelle.
Oltre ai tipi questi dbms offrono la possibilità di scrivere delle procedure direttamente nel linguaggio applicativo di riferimento (c++, java, ecc.) in accordo
alle caratteristiche degli odbms.
Una relazione, utilizzando questa tecnologia, si riduce, dal punto di vista
tecnico, ad una relazione unaria le cui tuple corrispondono ad oggetti. La complessità del linguaggio consente di produrre tuple con all’interno varie sottotuple,
offrendo la possibilità di descrivere in maniera complessa oggetti complessi.
Gli ORDBMS offrono la possibilità di riusare gli oggetti con il meccanismo
delle gerarchie che possono essere di Tipo o di Tabella, in accordo a quanto
avviene nel paradigma object-oriented.
La tecnologia degli ORDBMS sebbene, come già detto, non rivoluzionaria
ha avuto grande successo, in quanto molti dei maggiori produttori di RDBMS
se ne sono interessati, favorendo cosı̀ il suo rapido sviluppo. Ad oggi i database
Oracle, Microsoft SQL Server e l’IBM col suo DB2 suportano questa tecnologia.
Capitolo 2
MongoDB
MongoDB è un’implementazione in C++ di un DBMS document-oriented. Sul
sito ufficiale di riferimento (http://www.mongodb.org) le caratteristiche chiave
del sistema portano ad una rassicurante tagline:
MongoDB (from “humongous”) is a scalable, high-performance,
open source, document-oriented database.
Nei prossimi paragrafi si scenderà nel dettaglio delle caratteristiche del sistema, grazie alle quali questo riesce a coprire il vuoto tra i sistemi chiave-valore veloci e altamente scalabili - ed i classici RDBMS - che presentano un set completo di funzionalità e ricchezza di query, a fronte di una maggiore complessità
e pesantezza.
2.1
Document-oriented storage
E’ possibile implementare database doc-oriented realizzando uno strato software da porre su un database ad oggetti relazionale (ORDBMS) oppure partendo da un database orientato agli oggetti (OODBMS). Nel primo caso gli
oggetti prenderanno posto direttamente nel database e saranno resi disponibili
attraverso query in un apposito linguaggio.
MongoDB segue il secondo approccio, quello in cui si utilizzano oggetti persistenti in un linguaggio di programmazione orientato agli oggetti ed un set di
API per memorizzare e recuperare gli oggetti stessi.
Dal paradigma doc-oriented eredita il meccanismo di storage: non si memorizzano i dati in tabelle con campi uniformi per ogni record come nei database
relazionali, ma ogni record è memorizzato come un documento (un oggetto persistente, quindi) che possiede determinate caratteristiche. Qualsiasi numero
di campi con qualsiasi lunghezza può essere aggiunto al documento. I campi
possono anche contenere pezzi multipli di dati.
Un esempio concreto di documento contenente informazioni su di un viaggio,
potrebbe essere il seguente:
{
” id ” :
” rev ” :
”9 a826400d60073813c6f62508f9260e5 ” ,
” 1 −1915117622 ” ,
9
10
CAPITOLO 2. MONGODB
” type ” :
” destination ” :
” dates ” :
” Travel ” ,
” Tokio ” ,
{
” from ” : ” 15/07/2010 ” ,
” to ” :
” 10/08/2010 ”
},
” p a r t i c i p a n t s ” : [ ” S i l v e s t r o ” , ” Luca ” , ” Pippo ” ]
}
Per inquadrare subito le potenzialità di un simile approccio immaginiamo di
voler aggiungere in un secondo momento, in una applicazione già in produzione
su i viaggi effettuati, informazioni relative ad i mezzi di trasporto usati ed il
clima incontrato. Basterebbe estendere in questo modo il documento:
{
” id ” :
” rev ” :
” type ” :
” destination ” :
” dates ” :
”9 a826400d60073813c6f62508f9260e5 ” ,
” 1 −1915117622 ” ,
” Travel ” ,
” Tokio ” ,
{
” from ” : ” 15/07/2010 ” ,
” to ” :
” 10/08/2010 ”
},
” p a r t i c i p a n t s ” : [ ” S i l v e s t r o ” , ” Luca ” , ” Pippo ” ] ,
” u s i n g ” : [ ” c a r ” , ” bus ” , ” a i r p l a n e ” ] ,
” w e a t h e r s ” : [ ” sunny ” , ” c l o u d y ” ]
}
Normalizzazione vs Incorporamento In un modello relazionale sinonimo
di qualità di un database è il livello di normalizzazione adottato per le sue tabelle (salvo poi rinunciarvi a favore di maggiori performance). Proprietà di una
certa rilevanza per l’applicativo vengono quindi solitamente promosse ad Entità
separate, referenziate con l’Entità originaria, in modo da non perderne semantica e contenuto informativo. Nei doc-oriented si segue un indirizzo opposto,
accorpando quanto più possibile gli oggetti, creando macro-entità dal massimo
contenuto informativo, che risucchiano/incorporano tutte le informazioni di cui
necessitano per una determinata semantica.
Collezioni e linee guida Quando un oggetto viene promosso nel mondo docoriented viene creata una collezione per tutti gli oggetti dello stesso tipo. Ci
sono alcune semplici considerazioni che possono chiarire in quali caso l’incorporamento di oggetti in altri oggetti o la creazione di collezioni possa condurre ad
una sensibile variazione positiva in termini di performance:
ˆ gli oggetti progettati per contenere altri oggetti, incorporano questi ultimi
ˆ le relazioni molti a molti sono generalmente risolte per riferimento
ˆ collezioni con pochi oggetti possono non essere accorpate se l’applicazione
permette un buon livello di caching
ˆ gli oggetti incorporati, diversamente da quelli di primo livello nella root
della collezione, difficilmente possono essere referenziati
2.2. SUPPORTO COMPLETO INDICI
11
ˆ incorporare oggetti rende difficile realizzare viste di livello più profondo di
quello principale per la collezione
ˆ c’è un limite di natura fisica (gli oggetti sono salvati in file) che limita le
dimensioni per un singolo oggetto
ˆ se l’applicazione richiede performance elevate, l’incorporamento è una
soluzione efficace
2.2
Supporto completo Indici
Come in tutti i DBMS che si rispettino anche ai doc-oriented è richiesta la
presenza di indici. Cosı̀, in MongoDB:
ˆ il campo id è indicizzato automaticamente
ˆ i campi sui quali è tipico eseguire ricerche o acceduti di frequente andrebbero indicizzati
ˆ i campi su cui sono definiti ordinamenti generalmente andrebbero indicizzati
MongoDB fornisce strumenti in grado di suggerire su quali campi sia opportuno definire indici, dove non ve ne fossero. Vale ovviamente come regola
del pollice alto privileggiare campi di collezioni con un alto rapporto letture/scritture (applicazioni read-intensive), avendo gli indici peso prestazionale nelle
scritture ed esaltando le letture.
Resta comunque vero che gli indici vanno utilizzati preferibilmente se il
campo è realmente selettivo.
Gli indici sono utilizzati per migliorare le performance delle interrogazioni del
database. E’ importante pianificare che tipo di interrogazioni saranno effettuate
sul sistema per scegliere il giusto indice.
In MongoDB, un indice è una struttura dati che cataloga le informazioni
circa i valori dei campi specificati nei documenti in una collezione.
La struttura dati che realizza l’indice è utilizzata dall’ottimizzatore delle
query per ordinare velocemente i documenti all’interno della collaction trattando
un insieme di dati più leggero (l’indice appunto, invece che l’intera collaction).
In MongoDB la struttura dati utilizzata per implementare gli indici è il B-Tree.
Una volta definito un indice su uno o più campi sarà compito del sistema provvedere a mantenere aggiornato l’indice e di riflesso fornire performance
maggiori sulle letture che interrogano i campi chiave.
Direttamente dalla shell di Mongo è possibile definire chiavi:
semplici realizzate indicando il campo di una collection come campo indice.
composta realizzate indicando come campo indice un insieme di due o più
campi.
documento realizzate indicando come campo dell’indice un campo che
contiene oggetti. In questo caso solo interrogazioni con ordinamento casuale
avranno senso, mentre per interrogazioni ordinate converrà considerare chiavi
composte.
array realizzate indicando come campo dell’indice un campo che contiene
un array. In questo caso ogni elemento dell’array sarà ordinato.
12
CAPITOLO 2. MONGODB
E’ possibile inoltre definire un indice sparso su un determinato campo, cosı̀
facendo nell’indice saranno compresi solo gli oggetti che presentano il campo
indicato, mentre quelli che non lo presentano verranno filtrati.
Definire un indice univoco permetterà di esser sicuri che non sia possibile
per due oggetti differenti memorizzare lo stesso valore per il campo definito
come chiave univoca.
Caratteristica peculiare di MongoDB è la possibilità di utilizzare indici geospaziali bidimensionali. Una volta definito un indice geospaziale sarà possibile interrogare la collezioni con query basate sulla posizione geospaziale del
tipo trova gli N elementi più vicini alla mia posizione o criteri più specifici del
tipo trovami gli N musei più vicini alla mia posizione.
2.3
Replication
La replicazione è utilizzata per rimediare a malfunzionamenti ed introdurre
ridondanza dei dati nella base dati, sempre a scopo di prevenzione.
MongoDB realizza la replicazione in due modalità:
Master-Slave solo il nodo che funge da master modifica direttamente la base
dati, lo slave viene periodicamente sincronizzato con il master ed utilizzato per
le letture. In questo modo in ambito distribuito si assicura una consistenza
assoluta sul master ed una consistenza relativa sullo slave, nel senso che
prima o poi lo slave risulterà sincronizzato con il master.
Replica Sets è una elaborazione del modello Master-Slave che aggiunge il
ripristino automatico dopo un malfunzionamento ed il supporto di cluster di
server con membri primari (master) e secondari (slave).
2.4
Auto-Sharding
Lo sharding è una tecnica utilizzata all’interno dei database per il partizionamento orizzontale. Nel partizionamento verticale - la normalizzazione - una
tabella viene splittata in più tabelle dividendo i domini (campi) della tabella
stessa in modo da separare ed isolare semantiche omogenee. Nel partizionamento orizzontale lo split è realizzato in modo da ottenere due o più insiemi di tuple
da sistemare in due o più tabelle.
Lo sharding estende il concetto di partizionamento orizzontale permettendo
di avere agli shard - ovvero le partizioni ottenute dal db di partenza - di essere
slegati completamente gli uni dagli altri. In particolare:
ˆ ogni shard può vivere in una istanza dello schema logico totalemente
separato;
ˆ il server fisico del database che ospita lo shard può essere diverso da quello
degli altri;
ˆ il data center può essere qualsiasi, addirittura trovarsi in un altro continente.
2.4. AUTO-SHARDING
13
I vantaggi del partizionamento realizzato sulla base dati iniziale sono diversi:
ˆ è ridotto il numero totale di righe di ogni tabella coinvolta;
ˆ le dimensioni degli indici è ridotto, le ricerche risultano più efficienti;
ˆ ogni shard può essere posizionato su hardware differente, permettendo cosı̀
di ottenere performance superiori grazie al parallelismo;
ˆ la segmentazione dei dati può seguire in maniera più naturale quello del
mondo reale per una migliore gestione e separazione.
Un esempio su un reale utilizzo dello sharding ne può chiarire l’utilità. Tale
tecnica infatti si presta particolarmente per tabelle che prevedno intrinsecamente un raggruppamento per l’ambito applicativo di interesse. Possiamo allora
considerare un portale di commercio elettronico di vaste proporzioni con due
mercati relativamente separati come Europa e Stati Uniti.
In un contesto simile lo sharding prevede di realizzare due tabelle separate identiche strutturalemente - con i dati relativi ai prodotti destinati al mercato
statunitense e quelli relitivi al mercato europero.
E’ possibile addirittura prevedere che tali tabelle siano fisicamente implementate su due server distinti, geograficamente localizzati in modo da aumentare le performance - quindi probabilmente uno negli U.S.A e uno nel vecchio
continente.
Una soluzione del genere è auspicabile sia che vi sia una netta separazione
tra i due mercati - politiche aziendali potrebbero ad esempio proibire spedizioni
intercontinentali e quindi avrebbe perfettamente senso non permettere acquisti
di articoli americani in Europa e viceversa - sia che sia possibile fare richieste
ad un continente diverso dal proprio.
La logica si complicherebbe ma i vantaggi sarebbero comunque esaltati. Immaginando infatti che le richieste per prodotti in un altro continente - o su scala
mondiale - siano meno frequenti si può immaginare uno scenario nel quale server
slave continentali aggiornino periodicamente un master globale che ha visione
quindi completa sul reale stato del magazzino mondiale dello store.
E’ chiaramente una gestione che comporterebbe un maggior carico di lavoro
ed una visione non in tempo reale dello stato del sistema, ma che permetterebbe
comunque di ottimizzare le operazioni più frequenti del sistema senza rinunciare
alla visione - differita - globale.
Auto-Sharding è il meccanismo attraverso il quale MongoDB segmenta automaticamente una collezione una volta impostata una chiave sulla quale eseguire lo sharding. La collezione viene riallocata in più collezioni strutturalmente
identiche cercando di fare in modo che le dimensioni in termini di oggetti o occupazione di spazio siano bilanciate tra gli shard - le collezioni in cui è stata
segmentata la collezione iniziale.
Supponiamo di avere una collezione con un migliaio di oggetti al suo interno e di volere eseguire lo sharding su di un campo a della collezione iniziale.
MongoDB provvederà a realizzare m collezioni shard ognuna con un numero
bilanciato di oggetti. Quando sarà necessario effettuare ricerche sulla collezione iniziale MongoDB interrogherà un’apposita tabella per sapere a quali shard
rivolgersi per ottenere i corrispondenti oggetti.
14
CAPITOLO 2. MONGODB
2.5
Querying
Una delle più importanti caratteristiche di MongoDB è la sua capacità di supportare query dinamiche (ad hoc). I sistemi che supportano le query dinamiche
non richiedono degli indici speciali per trovare i dati; gli utenti possono trovare i dati usando un qualsiasi criterio. Le query dinamiche sono caratteristiche
dei database relazionali, pertanto, se si decide di migrare dati da un database relazionale verso un MongoDB si scoprirà che molte query SQL verranno
trasformate facilmente in query del linguaggio document-based.
Il mongodb supporta varie query-object per recuperare dati. Utilizza un
pattern modellato su BSON document. MongoDB supporta una vasta gamma
di selettori per i documenti.
Tra le possibili query effettuabili notiamo:
Selettore di campo è possibile specificare di mostrare nei risultati solo un
sottoinsieme di campi. In maniera analoga a quanto avviene nella SELECT
di SQL, l’unica differenza è che il campo id è sempre ritornato, anche quando
non specificato.
Selezione è possibile indicare criteri attraverso i quali recuperare un sottoinsieme dei documenti in una collection. In maniera uguale a quanto si fa in SQL
con la WHERE. E’ possibile ovviamente utilizzare per la selezione, come in
SQL:
ˆ operatori condizionali (and, or, nor, in, nin, all, exists, mod, size, type,
ne)
ˆ espressioni regolari
ˆ valori in array
ˆ valori negli oggetti embedded
ˆ meta operatori (not)
ˆ operatore di aggregazione (group)
Ordinamenti le query in MongoDB possono ritornare risultati ordinati in
maniera crescente o decrescente, specificando oppurtanamente su quale campo
eseguire l’ordinamento. In maniera analoga a quanto avviene con la clausola
ORDER BY in SQL.
Skip & Limit sono le opzioni tramite le quali effettuare la paginazione dei
risultati in maniera semplice. In maniera equivalente in SQL si trovano gli stessi
operatori.
E’ importante sottolineare come i risultati di una query vengano gestiti.
MongoDB utilizza la tecnica dei cursori, questi sono usati per recuperare
iterativamente tutti i documenti ritornati dalla query eseguita.
Capitolo 3
MongoDB HowTo
3.1
Installazione
In questo capitolo si illustra la procedura di installazione per MongoDB e le
operazioni comuni che ci si aspetta da un DBMS.
1. Download dei file all’indirizzo http://www.mongodb.org/display/DOCS/Downloads
2. Estrazione dei file in una directory qualsiasi (da questo momento tale
cartella sarà indicata come install dir )
3. Creazione della directory root per i dati del database, di default tale
directory è C:\data\db
4. Lancio del demone mongod.exe dalla cartella install dir \bin
Figura 3.1: Avvio demone mongod
15
16
CAPITOLO 3. MONGODB HOWTO
5. Lancio della shell di comando mongo.exe dalla cartella install dir \bin
Figura 3.2: Avvio della shell mongo
NOTA: nella versione a 32bit sussistono alcune limitazione in termini
di dimensioni di file che incidono sulle dimensioni del db stesso.
3.1.1
Utilizzo avanzato del demone mongod
E’ possibile specificare parametri al lancio del demone mongod:
logging Per ridirezionare il logging del server è sufficiente indicare dove locare il file di log e come appendere i dati di log semplicemente con il comando
seguente:
> . / mongod −−f o r k −−l o g p a t h / v a r / l o g /mongodb . l o g −−l o g a p p e n d
path db Può risultare comodo decidere esplicitamente dove salvare tutti i dati
relativi a database e collezioni con il seguente comando:
> . / mongod −−dbpath / v a r / l i b /mongodb/
porta E’ inoltre possibile modificare la porta di ascolto del server con il
comando:
> . / mongod −−p o r t 12345
3.2. GESTIONE DATABASE
3.2
17
Gestione Database
La shell di mongoDB permette di interrogare i database ed il sistema attraverso semplici comandi, elencabili attraverso il comando db.help()
> db . h e l p ( )
DB methods :
db . addUser ( username , password [ , readOnly=f a l s e ] )
db . auth ( username , password )
db . c l o n e D a t a b a s e ( f r o m h o s t )
db . commandHelp ( name ) r e t u r n s t h e h e l p f o r t h e command
db . copyDatabase ( fromdb , todb , f r o m h o s t )
db . c r e a t e C o l l e c t i o n ( name , { s i z e : . . . , capped : . . . , max : . . . }
)
db . currentOp ( ) d i s p l a y s t h e c u r r e n t o p e r a t i o n i n t h e db
db . dropDatabase ( )
db . e v a l ( func , a r g s ) run code s e r v e r −s i d e
db . g e t C o l l e c t i o n ( cname ) same a s db [ ' cname ' ] o r db . cname
db . g e t C o l l e c t i o n N a m e s ( )
db . g e t L a s t E r r o r ( ) − j u s t r e t u r n s t h e e r r msg s t r i n g
db . g e t L a s t E r r o r O b j ( ) − r e t u r n f u l l s t a t u s o b j e c t
db . getMongo ( ) g e t t h e s e r v e r c o n n e c t i o n o b j e c t
db . getMongo ( ) . s e t S l a v e O k ( ) a l l o w t h i s c o n n e c t i o n t o r e a d from t h e
nonmaster member o f a r e p l i c a p a i r
db . getName ( )
db . g e t P r e v E r r o r ( )
db . g e t P r o f i l i n g L e v e l ( ) − d e p r e c a t e d
db . g e t P r o f i l i n g S t a t u s ( ) − r e t u r n s i f p r o f i l i n g i s on and s l o w
threshold
db . g e t R e p l i c a t i o n I n f o ( )
db . g e t S i s t e r D B ( name ) g e t t h e db a t t h e same s e r v e r a s t h i s one
db . i s M a s t e r ( ) c h e c k r e p l i c a primary s t a t u s
db . k i l l O p ( o p i d ) k i l l s t h e c u r r e n t o p e r a t i o n i n t h e db
db . listCommands ( ) l i s t s a l l t h e db commands
db . p r i n t C o l l e c t i o n S t a t s ( )
db . p r i n t R e p l i c a t i o n I n f o ( )
db . p r i n t S l a v e R e p l i c a t i o n I n f o ( )
db . p r i n t S h a r d i n g S t a t u s ( )
db . removeUser ( username )
db . r e p a i r D a t a b a s e ( )
db . r e s e t E r r o r ( )
db . runCommand ( cmdObj ) run a d a t a b a s e command .
i f cmdObj i s a
s t r i n g , t u r n s i t i n t o { cmdObj : 1 }
db . s e r v e r S t a t u s ( )
db . s e t P r o f i l i n g L e v e l ( l e v e l ,< slowms >) 0= o f f 1=s l o w 2= a l l
db . s h u t d o w n S e r v e r ( )
db . s t a t s ( )
db . v e r s i o n ( ) c u r r e n t v e r s i o n o f t h e s e r v e r
db . getMongo ( ) . s e t S l a v e O k ( ) a l l o w q u e r i e s on a r e p l i c a t i o n s l a v e
server
18
3.2.1
CAPITOLO 3. MONGODB HOWTO
Selezione del database
Per poter gestire i database il primo comando da utilizzare è show dbs, in
modo da avere la lista dei database disponibili per il demone in running. Grazie
al comando use è possibile selezionare un database sul quale lavorare.
> show dbs
admin
0 . 0 7 8 1 2 5GB
local
( empty )
test
0 . 0 7 8 1 2 5GB
>u s e t e s t
s w i t c h e d t o db t e s t
>
3.2.2
Creazione del database
Per creare un database in MondoDB è necessario selezionare il database che
si vuole creare (mydb) tramite il comando use mydb per poi creare al suo
interno una prima collezione db.createCollection(nome collezione)
> u s e mydb
s w i t c h e d t o db mydb
> show dbs
admin
0 . 0 7 8 1 2 5GB
local
( empty )
test
0 . 0 7 8 1 2 5GB
> db . c r e a t e C o l l e c t i o n ( ” m y c o l l e c t i o n ” )
{ ” ok ” : 1 }
> show dbs
admin
0 . 0 7 8 1 2 5GB
local
( empty )
mydb
0 . 0 7 8 1 2 5GB
test
0 . 0 7 8 1 2 5GB
> db . g e t C o l l e c t i o n N a m e s ( )
[ ” m y c o l l e c t i o n ” , ” system . i n d e x e s ” ]
>
3.2.3
Eliminazione del database
Per eliminare un database in MondoDB è necessario selezionare il database
che si vuole creare (mydb) tramite il comando use mydb per poi utilizzare il
comando db.dropDatabase()
> show dbs
admin
0 . 0 7 8 1 2 5GB
local
( empty )
mydb
0 . 0 7 8 1 2 5GB
test
0 . 0 7 8 1 2 5GB
> db . dropDatabase ( )
{ ” dropped ” : ”mydb” , ” ok ” : 1 }
> show dbs
3.2. GESTIONE DATABASE
admin
local
test
>
0 . 0 7 8 1 2 5GB
( empty )
0 . 0 7 8 1 2 5GB
19
20
CAPITOLO 3. MONGODB HOWTO
3.3
Gestione Utenti
3.3.1
Creazione Utente
Per creare un utente in un database è necessario selezionare il database per
poi utilizzare il comando db.addUser(nome, password [, readOnly=false])
> db . addUser ( ” Cavani ” , ” matador ” , t r u e )
{
” u s e r ” : ” Cavani ” ,
” readOnly ” : t r u e ,
”pwd” : ” c 4 c 6 f 5 d 2 e 8 a e 9 5 a 8 5 a c 0 4 f f 9 8 0 c 9 9 0 5 5 ”
}
Il campo readOnly se settato su true specifica che l’utente avrà solo permessi
di lettura sul database.
Utenti Globali per associare un utente a tutti i db è sufficiente aggiungere
tale utente al db admin
3.3.2
Modifica Utente
Per modificare un utente è sufficiente utilizzare nuovamente il comando db.addUser(nome,
password [, readOnly=false])
> db . addUser ( ” L a v e z z i ” , ” pocho ” , t r u e )
{
” user ” : ” Lavezzi ” ,
” readOnly ” : t r u e ,
”pwd” : ” 70 f 7 b d 6 b 6 8 e 8 c 4 1 f e 6 1 2 c 6 8 b e 8 6 5 b 9 1 2 ”
}
> db . system . u s e r s . f i n d ( )
{ ” i d ” : O b j e c t I d ( ” 4 d 0 e 4 b 6 c a 7 3 8 0 0 0 0 0 0 0 0 4 c 8 a ” ) , ” u s e r ” : ” Cavani ” ,
” readOnly ” :
t r u e , ”pwd” : ” c 4 c 6 f 5 d 2 e 8 a e 9 5 a 8 5 a c 0 4 f f 9 8 0 c 9 9 0 5 5 ” }
{ ” i d ” : ObjectId ( ”4 d0e4bfba738000000004c8b ” ) , ” user ” : ” Lavezzi ” ,
” readOnly ” :
t r u e , ”pwd” : ” 70 f 7 b d 6 b 6 8 e 8 c 4 1 f e 6 1 2 c 6 8 b e 8 6 5 b 9 1 2 ” }
> db . addUser ( ” L a v e z z i ” , ” g o l e a d o r ” )
{
” i d ” : ObjectId ( ”4 d0e4bfba738000000004c8b ” ) ,
” user ” : ” Lavezzi ” ,
” readOnly ” : f a l s e ,
”pwd” : ” c 1 c 4 6 b f f e c 9 1 7 a 3 0 c 4 d 7 d 2 3 b 6 7 6 e a 6 4 8 ”
}
>
Da osservare come il sisteama riporti l’id del record utente in oggetto e come
la password venga per sicurezza salvata con un hash.
3.3.3
Eliminazione Utente
Per eliminare un utente è possibile utilizzare il comando db.removeUser(nome)
3.3. GESTIONE UTENTI
>
>
[
>
{
{
>
>
{
21
db . system . u s e r . f i n d ( )
db . g e t C o l l e c t i o n N a m e s ( )
” system . i n d e x e s ” , ” system . u s e r s ” ]
db . system . u s e r s . f i n d ( )
” i d ” : O b j e c t I d ( ” 4 d 0 d e 3 c b 5 b 1 8 0 0 0 0 0 0 0 0 3 a f c ” ) , ” u s e r ” : ” admin ” , ”
readOnly ” : f a l s e , ”pwd” : ” c 5 3 2 b 4 c 1 9 6 5 a d d a e 1 c 9 3 4 5 e 6 2 8 2 6 f b 5 2 ” }
” i d ” : O b j e c t I d ( ” 4 d 0 d e a 2 b 5 b 1 8 0 0 0 0 0 0 0 0 3 a f f ” ) , ” u s e r ” : ” admin1 ” ,
” readOnly ” : t r u e , ”pwd” : ” 5 a d a e 9 a 7 b 7 6 8 f d a 4 f d d 2 4 3 0 f 8 f 2 3 d 7 7 7 ” }
db . removeUser ( ” admin1 ” )
db . system . u s e r s . f i n d ( )
” i d ” : O b j e c t I d ( ” 4 d 0 d e 3 c b 5 b 1 8 0 0 0 0 0 0 0 0 3 a f c ” ) , ” u s e r ” : ” admin ” , ”
readOnly ” : f a l s e , ”pwd” : ” c 5 3 2 b 4 c 1 9 6 5 a d d a e 1 c 9 3 4 5 e 6 2 8 2 6 f b 5 2 ” }
3.3.4
Autenticazione Utente
MongoDB prevede due modalità di accesso: senza e con autenticazione. Chiaramente senza autenticazione si dà la possibilità a chiunque di accedere indiscriminatamente alle informazioni. E’ quindi buona norma prevedere l’autenticazione per gli utenti, in modo da scongiurare accessi non autorizzati.
Ci si può autenticare con username e password di un utente in un particolare
database, e l’utente stesso con il login ha attribuiti dei privilegi che possono
essere di sola lettura o di lettura-scrittura, a seconda del profilo dell’utente
associato all’username e password inseriti.
Il database admin è speciale, in quanto, un utente con determinati privilegi nel db admin è un utente con quei privilegi per ogni db, inoltre ha la
possibilità di eseguire delle operazioni di amministrazione che altrimenti non
potrebbe eseguire. Per abilitare questi controlli di sicurezza bisogna lanciare
il demone mongod con l’ opzione –auth, per farlo si deve aver creato precedentemente un utente nel database admin di amministrazione. Per effettuare il
login di amministrazione si deve selezionare il db admin e digitare il comando
db.auth(username, password) nella consolle mongo. Una volta fatto questo
si potrà accedere ad ogni altro db come se vi avessimo fatto il login.
% L a n c i o i l demone mongod
E : \ mongodb−win32−i 3 8 6 − 1 . 7 . 3 \ mongo\ bin>mongod −−auth
.................................................................
connecting to : t e s t
> show dbs
Mon Dec 27 1 4 : 0 5 : 2 2 uncaught e x c e p t i o n : l i s t D a t a b a s e s f a i l e d : {
” a s s e r t i o n ” : ” u n a u t h o r i z e d db : admin l o c k t y p e : −1 c l i e n t
:127.0.0.1” ,
” assertionCode ” : 10057 ,
” errmsg ” : ”db a s s e r t i o n f a i l u r e ” ,
” ok ” : 0
}
% non p o s s o f a r e i l l o g i n i n t e s t
> db . auth ( ” admin ” , ” a d m i n i s t r a t o r ” )
0
> show dbs
Mon Dec 27 1 4 : 0 6 : 1 8 uncaught e x c e p t i o n : l i s t D a t a b a s e s f a i l e d : {
22
CAPITOLO 3. MONGODB HOWTO
” a s s e r t i o n ” : ” u n a u t h o r i z e d db : admin l o c k t y p e : −1 c l i e n t
:127.0.0.1” ,
” assertionCode ” : 10057 ,
” errmsg ” : ”db a s s e r t i o n f a i l u r e ” ,
” ok ” : 0
}
% r i e s c o a l o g g a r m i n e l dbs admin
> u s e admin
s w i t c h e d t o db admin
> db . auth ( ” admin ” , ” a d m i n i s t r a t o r ” )
1
> show dbs
admin
0 . 0 7 8 1 2 5GB
local
( empty )
mydb
0 . 0 7 8 1 2 5GB
mydb1
0 . 0 7 8 1 2 5GB
test
0 . 0 7 8 1 2 5GB
%una v o l t a l o g g a t o da a m m i n i s t r a t o r e vado e vedo c i o che v o g l i o
> u s e mydb
s w i t c h e d t o db mydb
> db . g e t C o l l e c t i o n N a m e s ( )
[ ” system . i n d e x e s ” , ” system . u s e r s ” ]
>
Se si desidera creare un amministratore non dell’intero sistema ma solo di un
particolare db basta creare un utente al suo interno. Le credenziali di logging
di questo utente gli daranno dei privilegi solo all’interno del db stesso.
connecting to : t e s t
> u s e mydb
s w i t c h e d t o db mydb
> db . auth ( ” Localadmin ” , ” a m m i n i s t r a t o r e ” )
1
> db . g e t C o l l e c t i o n N a m e s ( )
[ ” system . i n d e x e s ” , ” system . u s e r s ” ]
% l a m m i n i s t r a t o r e l o c a l e non ha v i s i b i l i t a ' d e g l i a l t r i dbs
> show dbs
Mon Dec 27 1 4 : 2 7 : 5 3 uncaught e x c e p t i o n : l i s t D a t a b a s e s f a i l e d : {
” a s s e r t i o n ” : ” u n a u t h o r i z e d db : admin l o c k t y p e : −1 c l i e n t
:127.0.0.1” ,
” assertionCode ” : 10057 ,
” errmsg ” : ”db a s s e r t i o n f a i l u r e ” ,
” ok ” : 0
}
% anche s e c i puo e n t r a r e non ne ha v i s i b i l i t a ' d e i c o n t e n u t i
> u s e mydb1
s w i t c h e d t o db mydb1
> db . g e t C o l l e c t i o n N a m e s ( )
Mon Dec 27 1 4 : 2 5 : 5 4 uncaught e x c e p t i o n : e r r o r : {
” $ e r r ” : ” u n a u t h o r i z e d db : mydb1 l o c k t y p e : −1 c l i e n t : 1 2 7 . 0 . 0 . 1 ” ,
” code ” : 10057
}
>
3.3. GESTIONE UTENTI
23
24
3.4
CAPITOLO 3. MONGODB HOWTO
Gestione Collezioni
Come per i database è disponibile un helper specifico per le collection, utilizzando il comando db.nome collection.help()
> db . m y c o l l e c t i o n . h e l p ( )
DBCollection help
db . m y c o l l e c t i o n . f i n d ( ) . h e l p ( ) − show DBCursor h e l p
db . m y c o l l e c t i o n . count ( )
db . m y c o l l e c t i o n . d a t a S i z e ( )
db . m y c o l l e c t i o n . d i s t i n c t ( key ) − eg . db . m y c o l l e c t i o n . d i s t i n c t ( '
x' )
db . m y c o l l e c t i o n . drop ( ) drop t h e c o l l e c t i o n
db . m y c o l l e c t i o n . d r o p I n d e x ( name )
db . m y c o l l e c t i o n . d r o p I n d e x e s ( )
db . m y c o l l e c t i o n . e n s u r e I n d e x ( k e y p a t t e r n , o p t i o n s ) − o p t i o n s s h o u l d
be an o b j e c t with t h e s e p o s s i b l e f i e l d s : name , unique ,
dropDups
db . m y c o l l e c t i o n . r e I n d e x ( )
db . m y c o l l e c t i o n . f i n d ( [ query ] , [ f i e l d s ] ) − f i r s t p a r a m e t e r i s an
o p t i o n a l query f i l t e r . s e c o n d p a r a m e t e r i s o p t i o n a l s e t o f
f i e l d s t o r e t u r n . e . g . db . m y c o l l e c t i o n . f i n d ( { x : 77 } , {
name : 1 , x : 1 } )
db . m y c o l l e c t i o n . f i n d ( . . . ) . count ( )
db . m y c o l l e c t i o n . f i n d ( . . . ) . l i m i t ( n )
db . m y c o l l e c t i o n . f i n d ( . . . ) . s k i p ( n )
db . m y c o l l e c t i o n . f i n d ( . . . ) . s o r t ( . . . )
db . m y c o l l e c t i o n . findOne ( [ query ] )
db . m y c o l l e c t i o n . findAndModify ( { update : . . . , remove : b o o l [ ,
query : { } , s o r t : { } , ' new ' : f a l s e ] } )
db . m y c o l l e c t i o n . getDB ( ) g e t DB o b j e c t a s s o c i a t e d with c o l l e c t i o n
db . m y c o l l e c t i o n . g e t I n d e x e s ( )
db . m y c o l l e c t i o n . group ( { key : . . . , i n i t i a l : . . . , r e d u c e : . . . [ ,
cond : . . . ] } )
db . m y c o l l e c t i o n . mapReduce ( mapFunction , r e d u c e F u n c t i o n , <
o p t i o n a l params> )
db . m y c o l l e c t i o n . remove ( query )
db . m y c o l l e c t i o n . r e n a m e C o l l e c t i o n ( newName , <dropTarget> )
renames t h e c o l l e c t i o n .
db . m y c o l l e c t i o n . runCommand ( name , <o p t i o n s > ) r u n s a db command
with t h e g i v e n name where t h e f i r s t param i s t h e c o l l e c t i o n
name
db . m y c o l l e c t i o n . s a v e ( o b j )
db . m y c o l l e c t i o n . s t a t s ( )
db . m y c o l l e c t i o n . s t o r a g e S i z e ( ) − i n c l u d e s f r e e s p a c e a l l o c a t e d t o
this collection
db . m y c o l l e c t i o n . t o t a l I n d e x S i z e ( ) − s i z e i n b y t e s o f a l l t h e
indexes
db . m y c o l l e c t i o n . t o t a l S i z e ( ) − s t o r a g e a l l o c a t e d f o r a l l data and
indexes
db . m y c o l l e c t i o n . update ( query , o b j e c t [ , u p s e r t b o o l , m u l t i b o o l ] )
db . m y c o l l e c t i o n . v a l i d a t e ( ) − SLOW
db . m y c o l l e c t i o n . g e t S h a r d V e r s i o n ( ) − o n l y f o r u s e with s h a r d i n g
3.4. GESTIONE COLLEZIONI
25
NOTA: è possibile utilizzare un qualsiasi nome di collezione, anche di non
create, ottenendo ugualmente un help su di una generica collezione, completo
di tutti i comandi di default eseguibili sulle collezioni.
3.4.1
Creazione Collezione
Per creare una nuova collezione in un database è sufficiente selezionare il database di interesse ed invocare il metodo db.createCollaction(nome collezione)
> u s e mydb
s w i t c h e d t o db mydb
> db . g e t C o l l e c t i o n N a m e s ( )
[ ]
> db . c r e a t e C o l l e c t i o n ( ” C a l c i a t o r i ” )
{ ” ok ” : 1 }
> db . g e t C o l l e c t i o n N a m e s ( )
[ ” C a l c i a t o r i ” , ” system . i n d e x e s ” ]
>
3.4.2
Creazione Oggetto
Per creare un oggetto si può procedere in diversi modi:
In modo esplicito si crea l’oggetto - usando la sintassi JSON - e poi per
renderlo persistente nel database lo si inserisce all’interno di una collection, pertanto l’oggetto appena creato sarà visibile a tutti solo all’atto dell’inserimento
nella collection. Un oggetto creato resta utilizzabile a livello della sessione di
connessione finchè l’utente resta connesso, pertanto se lo si vuole è modificabile
e per eliminarlo lo si deve cancellare esplicitamente. L’ oggetto resta utilizzabile
anche se si cambia db come vedremo nella sezione Eliminazione Oggetto.
> c a l c i a t o r e = {nome : ”Marco” , cognome : ” M a t e r a z z i ” , p r e z z o : ” 10000
” }
{ ”nome” : ”Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ” }
> db . C a l c i a t o r i . i n s e r t ( c a l c i a t o r e )
> db . C a l c i a t o r i . f i n d ( )
{ ” i d ” : O b j e c t I d ( ” 4 d 0 e 5 3 5 c a 7 3 8 0 0 0 0 0 0 0 0 4 c 8 c ” ) , ”nome” :
, ” cognome ” : ” L a v e z z i ” , ” a l i a s ” : ” Pocho ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 0e5 41b a73 800 000 000 4c8 d ” ) , ”nome” :
” cognome ” : ” Cavani ” , ” a l i a s ” : ” Matador ” , ” bomber ”
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 2 9 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 3 ” ) , ”nome” :
cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ” }
” Ezequiel ”
” Edinson ” ,
: ” true ” }
”Marco” , ”
> db . C a l c i a t o r i . s a v e ( c a l c i a t o r e )
> db . C a l c i a t o r i . f i n d ( )
{ ” i d ” : O b j e c t I d ( ” 4 d 0 e 5 3 5 c a 7 3 8 0 0 0 0 0 0 0 0 4 c 8 c ” ) , ”nome” : ” E z e q u i e l ”
, ” cognome ” : ” L a v e z z i ” , ” a l i a s ” : ” Pocho ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 0e5 41b a73 800 000 000 4c8 d ” ) , ”nome” : ” Edinson ” ,
” cognome ” : ” Cavani ” , ” a l i a s ” : ” Matador ” , ” bomber ” : ” t r u e ” }
26
CAPITOLO 3. MONGODB HOWTO
{ ” i d ” : ObjectId ( ”4 d148829610f000000001b33 ” )
cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ”
{ ” i d ” : ObjectId ( ”4 d148842610f000000001b34 ” )
cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ”
, ”nome” : ”Marco” , ”
}
, ”nome” : ”Marco” , ”
}
In modo implicito si può creare un oggetto direttamente all’interno di una
collection, in questo caso l’oggetto non ha una vita propria ma la sua esistenza
è legata alla collection in cui lo si crea.
> db . C a l c i a t o r i . i n s e r t ( { nome : ” Pippo ” , cognome : ” I n z a g h i ” , r u o l o : ”
attaccante ” })
> db . C a l c i a t o r i . f i n d ( )
{ ” i d ” : O b j e c t I d ( ” 4 d 0 e 5 3 5 c a 7 3 8 0 0 0 0 0 0 0 0 4 c 8 c ” ) , ”nome” : ” E z e q u i e l ”
, ” cognome ” : ” L a v e z z i ” , ” a l i a s ” : ” Pocho ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 0e5 41b a73 800 000 000 4c8 d ” ) , ”nome” : ” Edinson ” ,
” cognome ” : ” Cavani ” , ” a l i a s ” : ” Matador ” , ” bomber ” : ” t r u e ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 2 9 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 3 ” ) , ”nome” : ”Marco” , ”
cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 4 2 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 4 ” ) , ”nome” : ”Marco” , ”
cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 8 9 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 5 ” ) , ”nome” : ” Pippo ” , ”
cognome ” : ” I n z a g h i ” , ” r u o l o ” : ” a t t a c c a n t e ” }
> db . C a l c i a t o r i . s a v e ( { nome : ” Pippo ” , cognome : ” I n z a g h i ” , r u o l o : ”
attaccante ” })
> db . C a l c i a t o r i . f i n d ( )
{ ” i d ” : O b j e c t I d ( ” 4 d 0 e 5 3 5 c a 7 3 8 0 0 0 0 0 0 0 0 4 c 8 c ” ) , ”nome” : ” E z e q u i e l ”
, ” cognome ” : ” L a v e z z i ” , ” a l i a s ” : ” Pocho ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 0e5 41b a73 800 000 000 4c8 d ” ) , ”nome” : ” Edinson ” ,
” cognome ” : ” Cavani ” , ” a l i a s ” : ” Matador ” , ” bomber ” : ” t r u e ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 2 9 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 3 ” ) , ”nome” : ”Marco” , ”
cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 4 2 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 4 ” ) , ”nome” : ”Marco” , ”
cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 8 9 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 5 ” ) , ”nome” : ” Pippo ” , ”
cognome ” : ” I n z a g h i ” , ” r u o l o ” : ” a t t a c c a n t e ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 9 c 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 6 ” ) , ”nome” : ” Pippo ” , ”
cognome ” : ” I n z a g h i ” , ” r u o l o ” : ” a t t a c c a n t e ” }
>
3.4.3
Modifica Oggetto
Un oggetto può esistere a livello di sessione o all’interno di una collection:
ˆ Nel primo caso l’oggetto esiste a livello di sessione e le modifiche avvengono
tramite la ridefinizione di tutti gli attributi dell’oggetto stesso.
> calciatore
{
”nome” : ”Marco” ,
” cognome ” : ” M a t e r a z z i ” ,
” p r e z z o ” : ” 10000 ” ,
3.4. GESTIONE COLLEZIONI
27
” i d ” : ObjectId ( ”4 d148842610f000000001b34 ” )
}
> c a l c i a t o r e = {nome : ”Marco” , cognome : ” M a t e r a z z i ” , p r e z z o : ”
1000000 ” }
{ ”nome” : ”Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ”
1000000 ” }
> c a l c i a t o r e = { p r e z z o : ” 100 ” }
{ ” p r e z z o ” : ” 100 ” }
> calciatore
{ ” p r e z z o ” : ” 100 ” }
ˆ Nel secondo caso si accede ad un oggetto contenuto in una collection,
esistente indipendentemente dalla sessione, questo si può modificare col
comando: update(query, obj [, upsert bool, multi bool])
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 4 2 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 4 ” ) , ”nome” : ”
Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 8 9 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 5 ” ) , ”nome” : ”
Pippo ” , ” cognome ” : ” I n z a g h i ” , ” r u o l o ” : ” a t t a c c a n t e ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 9 c 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 6 ” ) , ”nome” : ”
Pippo ” , ” cognome ” : ” I n z a g h i ” , ” r u o l o ” : ” a t t a c c a n t e ” }
> db . C a l c i a t o r i . update ( { nome : ” Pippo ” } , { $ s e t : { cognome : ”
Esempio ” } } )
> db . C a l c i a t o r i . f i n d ( )
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 4 2 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 4 ” ) , ”nome” : ”
Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ” 10000 ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 8 9 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 5 ” ) , ”nome” : ”
Pippo ” , ” cognome ” : ” Esempio ” , ” r u o l o ” : ” a t t a c c a n t e ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 9 c 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 6 ” ) , ”nome” : ”
Pippo ” , ” cognome ” : ” I n z a g h i ” , ” r u o l o ” : ” a t t a c c a n t e ” }
>
Il mongodb prevede varie opzioni di modifica (3.1) per il comando update:
Opzione
$addToSet
$set
$unset
$inc
$push
$pushAll
$pull
$pullAll
$pop
$rename
Azione
aggiunge il valore all’array solo se questo non è già presente
setta il valore di un determinato campo
elimina un campo
incrementa di un particolare valore partendo dall’ammontare iniziale
aggiunge un valore ad un array
aggiunge più valori ad un array
rimuove un valore ad un array
rimuove più valori da un array
rimuove l’ultimo valore dall’array
rinomina il campo con un nuovo nome
Tabella 3.1: Tabella delle opzioni di modifica
28
CAPITOLO 3. MONGODB HOWTO
Inoltre si possono effettuare modifiche semplici con il comando save()
che permette di modificare un oggetto usando l’opzione upsert, se l’oggetto
esiste lo modifica se non esiste lo inserisce nella collection.
3.4.4
Eliminazione Oggetto
Per quanto riguarda la cancellazione va distinto il caso in cui l’oggetto sia interno
o meno ad una collection:
ˆ Nel caso in cui un oggetto sia definito all’interno di una sessione per venire
usato piu volte, si può ottenere la cancellazione dell’oggetto in due modi:
1. direttamente: si cancella l’oggetto usando direttamente la delete.
> c a l c i a t o r e = {nome : ”Marco” , cognome : ” M a t e r a z z i ” ,
p r e z z o : ” 1000000 ” }
{ ”nome” : ”Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ”
1000000 ” }
> calciatore
{ ”nome” : ”Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ” : ”
1000000 ” }
> delete calciatore
true
> calciatore
F r i Dec 24 1 3 : 1 1 : 4 6 R e f e r e n c e E r r o r : c a l c i a t o r e i s not
defined ( s h e l l ) :0
>
2. indirettamente: l’oggetto viene eliminato automaticamente alla chiusura della sessione. Nell’esempio è mostrato come l’oggetto persista
grazie alla sessione, anche su database diversi, essendo un oggetto allocato globalmente nella sessione. Una volta chiusa la sessione
l’oggetto non risulta più disponibile.
> c a l c i a t o r e = {nome : ”Marco” , cognome : ” M a t e r a z z i ” ,
p r e z z o : ” 1000000 ” }
{ ”nome” : ”Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ”
1000000 ” }
> calciatore
{ ”nome” : ”Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ”
1000000 ” }
> use t e s t
s w i t c h e d t o db t e s t
> calciatore
{ ”nome” : ”Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ”
1000000 ” }
. . To mydb . . .
> calciatore
{ ”nome” : ”Marco” , ” cognome ” : ” M a t e r a z z i ” , ” p r e z z o ”
1000000 ” }
> exit
bye
E : \ mongodb−win32−i 3 8 6 − 1 . 7 . 3 \ mongo\ bin>mongo
: ”
: ”
: ”
: ”
3.4. GESTIONE COLLEZIONI
MongoDB s h e l l v e r s i o n : 1 . 7 . 3
c o n n e c t i n g t o : mydb
> calciatore
F r i Dec 24 1 3 : 1 6 : 5 6 R e f e r e n c e E r r o r : c a l c i a t o r e
defined ( s h e l l ) :0
>
29
i s not
ˆ Nel secondo caso si deve cancellare un oggetto inserito in una collection,
per realizzare questa operazione si procede usando la remove(query ). Il
metodo in base alla query passata, effettuerà una scansione della collection, eliminando tutti gli oggetti che rispettino le condizioni della query.
> db . C a l c i a t o r i . f i n d ( )
{ ” i d ” : O b j e c t I d ( ” 4 d 0 e 5 3 5 c a 7 3 8 0 0 0 0 0 0 0 0 4 c 8 c ” ) , ”nome”
E z e q u i e l ” , ” cognome ” :
” L a v e z z i ” , ” a l i a s ” : ” Pocho ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 0e5 41b a73 800 000 000 4c8 d ” ) , ”nome”
Edinson ” , ” cognome ” :
” Esempio ” , ” a l i a s ” : ” Matador ” , ” bomber ” : ” t r u e ” }
{ ” i d ” : O b j e c t I d ( ” 4 d 1 4 8 8 8 9 6 1 0 f 0 0 0 0 0 0 0 0 1 b 3 5 ” ) , ”nome”
Pippo ” , ” cognome ” : ”E
sempio ” , ” r u o l o ” : ” a t t a c c a n t e ” }
> db . C a l c i a t o r i . remove ( { cognome : ” Esempio ” } )
> db . C a l c i a t o r i . f i n d ( )
{ ” i d ” : O b j e c t I d ( ” 4 d 0 e 5 3 5 c a 7 3 8 0 0 0 0 0 0 0 0 4 c 8 c ” ) , ”nome”
E z e q u i e l ” , ” cognome ” :
” L a v e z z i ” , ” a l i a s ” : ” Pocho ” }
3.4.5
: ”
: ”
: ”
: ”
Eliminazione Collezione
L’eliminazione di una collection comporta l’eliminazione di tutti gli oggetti
interni alla collection stessa, si effettua tramite il comando drop().
> db . c o l l P r o v a . i n s e r t ( { nome : ” prova ” } )
> db . c o l l P r o v a . p r o v a i n t e r n a 1 . i n s e r t ( { nome : ” prova ” } )
> db . g e t C o l l e c t i o n N a m e s ( )
[
” Calciatori ” ,
” collProva ” ,
” collProva . provainterna1 ” ,
” system . i n d e x e s ”
]
> db . c o l l P r o v a . drop ( )
true
> db . g e t C o l l e c t i o n N a m e s ( )
[
” Calciatori ” ,
” collProva . provainterna1 ” ,
” system . i n d e x e s ”
]
>
30
CAPITOLO 3. MONGODB HOWTO
Capitolo 4
Conclusioni
Il MongoDB è giunto ormai alla versione 1.6.5. Nel corso degli anni ha rafforzato le sue potenzialità, raggiungendo oggi una certa stabilità e diversi punti
di forza che lo caratterizzano:
ˆ l’auto-sharding e la possibilità di scalare in maniera orizzontale;
ˆ l’alta disponibilità dai dati;
ˆ il ripristino automatico dai guasti.
Nel corso degli anni le esigenze applicative relative alle basi di dati si sono
spostate dalla semplice catalogazione di file di testo, a delicate transazioni bancarie per poi arrivare oggi ad avere utilizzatori finali che non solo utilizzano
l’applicazione, ma dinamicamente, ogni giorno, la ridisegnano a proprio uso e
consumo.
E’ proprio questa forte spinta all’user-centric del web 2.0 che ha fatto esplodere il fenomeno di database meno tradizionali e nati proprio per le nuove generazioni di applicazioni. Oggi siamo molto vicini a quella che si profila essere la
nuova era del web, la sua terza generazione, con tutta l’attenzione posta sulla
semantica.
In un tale scenario le applicazioni che vedranno sempre più la luce saranno
applicazioni con un forte indice di evoluzione, in cui non solo nuove tipologie di
relazioni saranno all’ordine del giorno - se non dell’ora - ma persino il più piccolo
frammento di dato dovrà gravitare attorno ad oggetti flessibili ed in grado di
modellare realtà sempre diverse.
In tale ottica ecco venire alla luce soluzioni innovative come i documentoriented di cui MongoDB è un rappresentante di spicco, grazie anche a particoli
punti di forza sui quali può contare:
ˆ un driver client in ogni linguaggio: protocolli socket nativi per le interfacce
client/server (non REST);
ˆ uso di file memory mapped per la memorizzazione dei dati;
ˆ memorizzazione collection-oriented (le collezione sono archiviati in modo
contiguo);
ˆ consente l’update-in-place (non MVCC);
ˆ è scritto in C++.
31
32
CAPITOLO 4. CONCLUSIONI
Tutto questo accompagnato da scelte architetturali ed una implementazione che ne garantisce performance superiori ad altri sistemi analoghi ed un set
completo di funzionalità che lo pongono nel panorama attuale come una scelta
sicuramente vincente, se ciò di cui si ha bisogno è una piattaforma sufficientemente stabile ed al tempo stesso attenta a seguire strettamente i trend evolutivi
del mercato delle applicazioni.
Data questa sua propensione ad essere un sistema malleabile ed al tempo
stesso performante, il MongoDB potrebbe essere una buona scelta per supportare problemi come:
1. problemi in cui si vogliono avere delle prestazioni elevate come possono
essere quelli per la memorizzazione dei profili utenti di un sito web;
2. problemi in cui è richiesto un tasso di aggiornamento alto come avviene,
ad esempio, nell’aggiornamento dei contatori per l’analisi in tempo reale
dei siti web;
3. problemi in cui il labeling delle risorse è fondamentale e diversificato.
Capitolo 5
Appendice
5.A
Sintassi JSON
JSON (JavaScript Object Notation) è un semplice formato per lo scambio di
dati. Per le persone è facile da leggere e scrivere, mentre per le macchine risulta
facile da generare e analizzarne la sintassi.
I tipi supportati sono:
ˆ
ˆ
ˆ
ˆ
booleani (true e false);
interi, reali, virgola mobile;
stringhe racchiuse da doppi apici ( );
array (sequenze ordinate di valori, separati da virgole e racchiusi in parentesi quadre [ ] );
ˆ array associativi (sequenze coppie chiave-valore separate da virgole racchiuse in parentesi graffe);
ˆ null.
E’ possibile combinare tali tipi di dati in due strutture fondamentali:
ˆ un insieme di coppie nome/valore. In diversi linguaggi, questo è realizzato
come un oggetto, un record, uno struct, un dizionario, una tabella hash,
un elenco di chiavi o un array associativo.
ˆ un elenco ordinato di valori. Nella maggior parte dei linguaggi questo si
realizza con un array, un vettore, un elenco o una sequenza.
Oggetto è una serie non ordinata di nomi/valori. Un oggetto inizia con {
(parentesi graffa sinistra) e finisce con } (parentesi graffa destra). Ogni nome è
seguito da : (due punti) e la coppia di nome/valore sono separata da , (virgola).
v a r c a r = { ” e n g i n e ” : ” d i e s e l ” , ” w h e e l s ” : 4}
Array è una raccolta ordinata di valori. Un array comincia con [ (parentesi
quadra sinistra) e finisce con ] (parentesi quadra destra). I valori sono separati
da , (virgola).
33
34
CAPITOLO 5. APPENDICE
v a r f r u i t s = [ ” a p p l e ” , ” o r a n g e ” , ” banana ” ]
Valore può essere una stringa tra virgolette, o un numero, o vero o falso o
nullo, o un oggetto o un array. Queste strutture possono essere annidate.
Stringa è una raccolta di zero o più caratteri Unicode, tra virgolette; per le
sequenze di escape utilizza la barra rovesciata. Un singolo carattere è rappresentato come una stringa di caratteri di lunghezza uno. Una stringa è molto
simile ad una stringa C o Java.
Strutture composte è possibile combinare tutti i tipi di dati in strutture
complesse.
var car = {
” engine ” : ” d i e s e l ” ,
” wheels ” : 4 ,
” o p t i o n a l s ” : [ ” abs ” , ” e p s ” , ” a i r b a g ” : { ” d r i v e r ” : t r u e , ” s i d e ” :
t r u e , ” baby ” : f a l s e } ]
}
5.B. MIGRARE DA SQL A MONGODB
5.B
35
Migrare da SQL a MongoDB
Nella tabella 5.1 si mostra cosa offre mongo rispetto ad un database relazionale
come mysql.
Modello dei Dati
Tipi di Dato
Supporto Files
Schema di partizionamento orizzontale
Replicazione
Memorizzazione
Oggetti (Righe)
Metodi di Query
Indici secondari
Atomicità
Interfacce
Scritto in
Controllo di Concorrenza
Indici Geospaziali
Modello di Consistenza Distribuito
MongoDB
Document-Oriented (BSON)
string, int, double, boolean,
date, bytearray, object, array,
others
Si
Auto-Sharding(v1.6)
MySQL
Relazionale
tipi numerici, tipi date and time,
tipi string (character)
Master-slave (e replica sets)
Basata sulle Collection
Master-slave
Basata sulle tabelle
Linguaggio di query object-based
Si
Documenti Singoli
Driver Nativi ed add-on tipo
Rest
C++
modifica sul posto
SQL
Si
Si, avanzata
Driver Nativi
Si (da giugno 2010 il sistema
di coordinate è cartesiano, le
coordinate sferiche sono in corso
d’opera)
Consistenza rigida, sono disponibili le letture consistenti da siti
secondari
Supportati parzialmente
?
?
C++
?
Consistenza rigida, sono disponibili le letture consistenti da siti
secondari
Tabella 5.1: Tabella tecnica SQL MongoDB
La tabella 5.2 riporta alcune query Sql con il rispettivo equivalente in MongoDB, in cui è possibile notare l’uso degli oggetti JSON per le query.
36
CAPITOLO 5. APPENDICE
SQL Statement
CREATE TABLE USERS (a Number, b Number)
INSERT INTO USERS VALUES(1, 1)
SELECT a, b FROM users
SELECT * FROM users
SELECT * FROM users WHERE age = 33
SELECT a,b FROM users WHERE age = 33
SELECT * FROM users WHERE age = 33
ORDER BY name
SELECT * FROM users WHERE age>33
SELECT * FROM users WHERE age<33
SELECT * FROM users WHERE name
LIKE “%Joe%”
SELECT * FROM users WHERE name
LIKE “Joe%”
SELECT * FROM users
WHERE age>33 AND age<=40
SELECT * FROM users ORDER BY name DESC
CREATE INDEX myindexname ON users(name)
CREATE INDEX myindexname
ON users(name, ts DESC)
SELECT * FROM users WHERE a=1 and b = ‘q’
SELECT * FROM users LIMIT 10 SKIP 20
SELECT * FROM users WHERE a=1 or b=2
SELECT * FROM users LIMIT 1
EXPLAIN SELECT * FROM users WHERE z=3
SELECT DISTINCT last name FROM users
SELECT COUNT(*) FROM users
SELECT COUNT(*) FROM users
WHERE AGE > 30
SELECT COUNT(AGE) FROM users
UPDATE users SET a = 1 WHERE b = ‘q’
UPDATE users SET a = a+2 WHERE b = ‘q’
DELETE FROM users WHERE z = ‘abc’
Mongo Query Language Statement
implicito; può essere fatto
direttamente
db.users.insert({“a”: 1, “b”: 1})
db.users.find({}, {“a”: 1, “b”: 1})
db.users.find()
db.users.find({“age”: 33})
db.users.find({“age”: 33}, {“a”: 1, “b”:
1})
db.users.find({“age”:
33}).sort({“name”: 1})
db.users.find({“age”: {$gt: 33}})
db.users.find({“age”: {$lt: 33}})
db.users.find({“name”: /Joe/})
db.users.find({“name”: /ˆJoe/})
db.users.find({“age”: {$gt: 33, $lte:
40}})
db.users.find().sort({“name”: -1})
db.users.ensureIndex({“name”: 1})
db.users.ensureIndex({“name”:1, “ts”:1})
db.users.find({“a”: 1, “b”: ‘q’})
db.users.find().limit(10).skip(20)
db.users.find(
{ $or : [ {“a”: 1 } , {“b”: 2 } ] } )
db.users.findOne()
db.users.find({“z”: 3}).explain()
db.users.distinct(“last name”)
db.users.count()
db.users.find({“age”:{$gt:30}}).count()
db.users.find(
{“age”:{$exists: true}}).count()
db.users.update(
{“b”: ‘q’}, {$set: {“a”: 1}}, false, true)
db.users.update(
{“b”: ’q’}, {$inc:{“a”: 2}}, false, true)
db.users.remove({“z”: ‘abc’});
Tabella 5.2: Tabella comparativa SQL-MongoDB
Bibliografia
[1] P.Atzeni ed Altri. Basi di Dati. Architetture e linee di evoluzione. McGraw
Hill
[2] Wikipedia. Document-oriented Database. [http://en.wikipedia.org/wiki/Documentoriented database]
[3] Documentazione MongoDB [http://www.mongodb.org/display/DOCS]
[4] Dropping ACID with MongoDB [http://www.slideshare.net/kchodorow/droppingacid-with-mongodb]
[5] Wikipedia. MongoDB. [http://en.wikipedia.org/wiki/MongoDB]
37