MongoDB appartiene alla categoria di database documentali, che si pongono in netto contrasto con i classici e ormai noti a tutti database relazionali, come ad esempio MySQL. Per questo motivo i database come MongoDB sono detti NoSQL, proprio per la loro netta distinzione dalle caratteristiche tipiche dei database che utilizzano SQL. Come vedremo nel dettaglio, infatti, le idee e i contetti di base fanno emergere fin da subito le differenze sostanziali, distinguendo due veri e propri mondi separati. Questa guida è mirata a fornire un'introduzione a MongoDB e ai database documentali e ha lo scopo di guidare il lettore verso la loro comprensione e il loro utilizzo.

Differenza tra SQL e NoSQL

Iniziamo col fare chiarezza su questo punto ed elenchiamo le caratteristiche di ciascuna tipologia:

Database SQL

  • Salvano dati relazionali in tabelle
  • Richiedono la definizione di uno schema sulle tabelle prima dell'utilizzo
  • Supportano le JOIN per unire due o più tabelle che sono in relazione
  • Implementano delle regole per la preservazione dell'integrità dei dati
  • Utilizza le transazioni per garantire l'atomicità di due o più operazioni
  • Può scalare
  • Utilizza un linguaggio dichiarativo per le qu

Database NoSQL

  • Salva dati in formato simil-JSON, con documenti composti da attributi chiave-valore
  • Può salvare dati senza la specifica di uno schema
  • Non richiede JOIN
  • Permette ai dati di essere salvati ovunque e in qualsiasi momento senza alcuna verifica
  • È molto performante e scalabile
  • Utilizza il JSON per effettuare le query

I database SQL sono ideali per progetti dove i requisiti sono ben chiari e determinati e la robustezza ed integrità dei dati è essenziale. Al contrario i database NoSQL si prestano a scenari in cui i dati sono in continuo cambiamento e il loro schema non è stabile e dove la velocità e la scalabilità sono molto importanti. Per scalabilità si intende la capacità di adattarsi ad un aumento di domanda o carico di lavoro, per cui in questo caso i database NoSQL sono progettati e studiati per resistere ad un aumento considerevole del carico.

Cos'è MongoDB

MongoDB è un database di tipo documentale open-source scalabile e flessibile, che salva i dati in uno stile JSON. Tipicamente un database relazionale è composto da tabelle, ciascuna delle quali ha il suo set di colonne e dove ciascun record è una riga al suo interno. MongoDB di contro non possiede tabelle o colonne, ma lavora con una struttura molto simile al JSON, che permette un'enorme flessibilità. Vediamo subito un esempio:

{
   "_id": ObjectId(3da252d3902a),
   "title": "Welcome to MongoDB",
   "description": "Lorem ipsum dolor sit amet",
   "author": "Luca De Franceschi",
   "date": ISODate("2018-05-29T09:08:01.488Z")
}

L'oggetto appena visto viene chiamato document in MongoDB e corrisponde ad una riga in un database SQL. Un gruppo di document è conosciuto come collection, che simmetricamente a SQL può essere visto come una tabella. La differenza sostanziale è che in MongoDB non è necessario definire le colonne di una collection, ma la flessibilità è pressochè totale e ciascun document della medesima collection non necessariamente deve avere campi in comune.

Essendo JSON ciascun campo può essere di diversa tipologia, come ad esempio una stringa, un numero, una data ma anche un array o un altro oggetto. Inoltre ciascun campo può mutare il suo tipo nel corso del tempo a qualsiasi momento. Questa enorme flessibilità evita di dover creare più documenti e relazionarli tra loro, in quanto tutti i dati di cui si ha bisogno sono già salvati all'interno del record.

Installare MongoDB

L'installazione è piuttosto semplice e lineare e non richiede molta configurazione. MongoDB è supportato da tutte le meggiori piattaforme e distribuzioni. Per una maggiore documentazione ed istruzioni specifiche rivolgersi direttamente al sito ufficiale.

Una volta installato MongoDB lavorerà in background come servizio e sarà possibile accedervi da riga di comando o tramite un client grafico, come ad esempio robomongo.

MongoDB in azione

Vediamo ora alcuni comandi base per utilizzare MongoDB. Apriamo una shell di mongo e digitiamo:

$ mongo
MongoDB shell version v3.4.9
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.9
> use test
switched to db test

In questo caso abbiamo fatto accesso alla shell di mongo e ci siamo connessi al database test. Notare che il database se non esiste viene creato in tempo reale, per cui non è necessario doverlo creare manualmente. Per vedere la lista di tutti i database presenti basta digitare show dbs:

> show dbs
admin            0.000GB
local            0.000GB
test             0.000GB
touchmultimedia  0.000GB

Su ciascun database è possibile elencare tutte le collection esistenti tramite il comando:

> show collections
articles
users

Per inserire un nuovo document dobbiamo anzitutto specificare la collection di appartenenza e in seguito l'oggetto JSON di cui sarà composto. Supponiamo di voler inserire un document all'interno della collection articles:

> db.articles.insertOne({ title: "Test", description: "Lorem ipsum" })
{
  "acknowledged" : true,
  "insertedId" : ObjectId("5b3ca1ef1a1dc985fd62255d")
}

Come si può notare al document appena creato è stato assegnato un ObjectId. Questo valore è un esadecimale composto da 12 byte:

  • 4 byte rappresentano il numero di secondi dall'inizio dell'epoca Unix (1 Gennaio 1970). Per questo motivo è possibile risalire alla data di creazione di un document senza salvare un campo aggiuntivo
  • 3 byte sono identificatori della macchina
  • 2 byte rappresentano l'id del processo
  • 3 byte sono contatori, a partire da un numero casuale

ObjectId è una classe il cui costruttore accetta una stringa esadecimale come parametro opzionale. Sempre dalla shell di mongo è possibile generare un nuovo ObjectId in questo modo:

> x = ObjectId()
ObjectId("5b3cc5511a1dc985fd62255e")

Una volta creato il document è possibile effettuare una query per trovarlo:

> db.articles.find({ title: "Test" })
{ "_id" : ObjectId("5b3ca1ef1a1dc985fd62255d"), "title" : "Test", "description" : "Lorem ipsum" }

Il comando find restituisce tutti i document della collection specificata che soddisfano la query indicata. La query viene indicata come parametro del metodo ed è in formato JSON. Nell'esempio precedente sono stati estratti tutti i document appartenenti alla collection articles che abbiano come title "Test".

È possibile in qualsiasi momento modificare uno o più document esistenti inserendo, modificando o eliminando uno o più campi. Ad esempio se volessimo aggiungere il campo data all'articolo e aggiornare il titolo:

> db.articles.updateOne({ title: "Test" }, { $set: { title: "Test updated", date: ISODate("2018-05-29T09:08:01.488Z") }})
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

La funzione updateOne prende in questo caso una query come primo parametro e come secondo parametro un oggetto JSON di update, che specifica i campi da modificare tramite la keyword $set. Se ora rieseguiamo la query vedremo il document aggiornato:

> db.articles.find({ title: "Test updated" }).pretty()
{
  "_id" : ObjectId("5b3ca1ef1a1dc985fd62255d"),
  "title" : "Test updated",
  "description" : "Lorem ipsum",
  "date" : ISODate("2018-05-29T09:08:01.488Z")
}

In questo caso è stata usata in aggiunta la funzione pretty() che si occupa di stampare in output il document in un formato più leggibile.

È possibile infine rimuovere uno o più document da una collection tramite il comando deleteOne deleteMany:

> db.articles.deleteOne({ title: "Test updated" })
{ "acknowledged" : true, "deletedCount" : 1 }

In questo caso abbiamo eliminato il document creato in precedenza.

Conclusioni

MongoDB è un database documentale NoSQL che ha preso grande popolarità negli ultimi anni e viene utilizzato in molti ambiti, quali le applicazioni web, i social network o in generale in tutti gli scenari in cui la velocità, la flessibilità e la scalabilità sono un requisito fondamentale. In questa guida abbiamo solamente scandagliato alcuni degli argomenti e degli aspetti relativi a MongoDB, ma in realtà il suo utilizzo può essere ben più complesso e strutturato.