MongoDB: differenze rispetto ai database relazionali, l'installazione in CentOS, e primo utilizzo da linea di comando
MongoDB è un sistema di gestione di database (DBMS) orientato ai documenti, open source quindi gratuito, scritto in C++, che salva i dati in documenti di tipo JSON (JavaScript Object Notation).
Confronto tra database relazionali e MongoDB
Nei classici database relazionali (RDBMS: Relational Database Management Systems), come MySQL, abbiamo i concetti di database, tabelle, righe e colonne.
In MongoDB:
- i database continuiamo a chiamari database
- al posto delle tabelle abbiamo le collezioni (collection)
- al posto delle righe (records) abbiamo i documenti o oggetti
- al posto delle colonne abbiamo i campi, composti da coppie chiave-valore
In Mongo, quindi, un database è un insieme di collezioni, ed una collezione è un insieme di documenti.
Il limite di un database MongoDB, rispetto ai database relazionali, è l'assenza di JOIN e TRANSACTION, questo per preservare la velocità di Mongo, anche se come alternativa alle JOIN esistono le PRE-JOIN, che vedremo tra poco.
Un documento di MongoDB è quindi una collezione di coppie chiave-valore, in formato JSON, con una dimensione massima di 16 MB. Va considerato come un oggetto, in una programmazione ad oggetti, per cui parlare di oggetto o di documento è la stessa cosa.
In un database relazionale avremo una tabella così strutturata, con 3 records
name | age |
ronaldo | 34 |
ibrahimovic | 38 |
insigne | 29 |
mentre in Mongo per ogni record (documento) avremo un classico oggetto json, una stringa racchiusa tra parentesi graffe, che contiene coppie chiave/valori, separate da virgola.
{
"name":"ronaldo",
"age": 34
}
{
"name":"ibrahimovic",
"age": 38
}
{
"name":"insigne",
"age": 29
}
Chiavi e valori in JSON
In JSON la chiave è sempre una stringa, ad esempio "name", e per questo le chiavi vanno racchiuse tra virgolette (anche se, nella shell di mongo che vedremo, possiamo ometterle a patto che la chiave inizi con una lettera)
I possibili valori in json possono essere di sei tipologie:
- una stringa (racchiusa tra virgolette)
- un numero (senza virgolette)
- un bolleano (true false)
- null per i valori nulli
- gli array cioè liste ordinate racchiuse tra parentesi quadre (e può contenere numeri, stringhe...).
- oggetti, o documenti, intesi come mappe associative chiave valore, caratterizzate dalle parentesi graffe, in pratica un oggetti json racchiuso in un json
La chiave obbligatoria "_id"
In MongoDB ogni documento deve avere OBBLIGATORIAMENTE una chiave chiamata "_id": è un attributo speciale di tipo "ObjectId", un indice, ed in sua assenza automaticamente aggiunto da Mongo in fase di creazione del documento.
Ad esempio:
{
"_id" : ObjectId("5f86e7adb8927708451222bb"),
"name":"ronaldo",
"age": 34
}
Caratteristiche di MongoDB
Scalabilità: se il traffico sul sito aumenta, anche le richieste al database saranno maggiori. Nei database relazionali, normalmente, si utilizza una scalabilità di tipo verticale, cioè si passa da un piccolo server, ad un server con prestazioni maggiori. In MongoDB la scalabilità è orizzontale e ci vengono offerti due strumenti per realizzarla:
- la replication: è la replica fisica dei dati da un server "primario" e dei server "secondari". Mongo si occuperà di mantenere i server sincronizzati, e nel caso in cui il server primario risulti irraggiungibile, erege un server secondario a prendere il suo posto.
- la auto-sharding: ci consente di distribuire, di separare, i dati su più server, e sarà Mongo a distrubuire i carichi di dati e a tenerli bilanciati
Disponibilità: MongoDB garantisce l'alta disponibilità dei dati, attraverso il processo di sincronizzazione (replica) dei dati tra più server, in modo da avere più copie dei dati su diversi server di database, per cui se un singolo server dovesse danneggiarsi, i dati sono comunque disponibili in altri server.
Flessibilità: il progetto può adeguarsi dinamicamente in qualsiasi momento. Si parla anche di schema "dinamico", cioè possiamo facilmente e rapidamente modificare la struttura del database in base alle esigenze, ad esempio aggiungendo un campo, senza dover intervenire in modo "pesante", come normalemente viene fatto per database relazionali, aggiungendo semplicemente un campo nel documento json.
Le PRE-JOIN in MongoDB (o incapsulamento o embedding)
Sono un modo per superare l'assenza delle JOIN in Mongo, e vengono anche chiamate con i termini "embedding" o "incapsulazione".
In poche parole, il documento già contiene al suo interno i dati che avrei dovuto ottenere con una JOIN.
Ripartiamo dall'esempio precedente e consideriamo per semplicità un solo documento (record).
In un database relazionale abbiamo due tabelle: una relativa ai "giocatori" e una relativa ai "campionati vinti" da questi giocatori, e per visualizzare i dati di un giocatore dovremmo unire le due tabella con una join.
name | age |
ronaldo | 34 |
anno | competizione |
2002 | Supercoppa portoghese |
2003 | Coppa d'Inghilterra |
2019 | Serie A |
Invece, in Mongo il documento conterrà, incapsulate al suo interno, già tutte le informazioni relative ai campionati vinti, utilizzando un array json.
{
"_id" : ObjectId("5f86e7adb8927708451222bb"),
"nome":"ronaldo",
"eta": 34,
"vittorie": [
{
"anno":"2002",
"competizione":"Supercoppa portoghese"
}
{
"anno":"2003",
"competizione":"Coppa d'Inghilterra"
}
{
"anno":"2019",
"competizione":"Serie A"
}
]
}
Con l'incapsulamento non dobbiamo fare una JOIN, e la velocità di caricamento dati sarà maggiore.
Questa incapsulamento però va utilizzato tenendo conto dei dati da visualizzare agli utenti.
Facciamo un nuovo esempio, un blog: abbiamo un documento che contiene il titolo, l'autore, e una lista di commenti, ed ogni commento avrà come chiavi il nome dell'autore ed il testo del commento.
{
"_id" : ObjectId("5099803df3f4948bd2f98391"),
"titolo":"Parliamo del linguaggio PHP",
"testo":"Prova prova prova prova prova ....",
"autore":"Mario Rossi",
"commenti":[
{"nome":"giulio", "testo": "ciao da giulio"},
{"nome":"elisa", "testo": "questo blog è molto interessante"},
]
}
I commenti potrebbero diventare tantissimi (e anche sforare, ma è difficile, la soglia dei 16 Mb prevista a documento).
Potremmo quindi decidere di mostrare subito i primi 20 commenti, e poi mettere una paginazione, per cui, cliccando sulla pagina successiva, potremmo vedere altri commenti, e così via. Gli altri commenti li mettereno in una collection separata.
Ecco che nel nostro documento non dovremo salvare tutti i commenti, ma solo i primi 20 (che sono gli ultimi salvati), quindi in un array a dimensione fissa.
Esiste un operatore, da utilizzare in fase di inserimento, e che vedremo successivamente, che consente proprio di limitare un array a dimensione fissa, nel nostro caso a 20 commenti, e gli altri verranno inseriti in collection separate.
Se utilizziamo un array a dimensione fissa, aggiungiamo due chiavi al nostro documento, una per tener traccia del numero totale di commenti, e la seconda per il numero totale di pagine generate per i commenti.
Ad esempio se abbiamo 86 commenti, divisi in blocchi da 20, avremo quindi 5 pagine di commenti (questa più altre 4).
{
"_id" : ObjectId("5099803df3f4948bd2f98391"),
"titolo":"Parliamo del linguaggio PHP",
"testo":"Prova prova prova prova prova ....",
"autore":"Mario Rossi",
"commenti":[
{"nome":"giulio", "testo": "ciao da giulio"},
{"nome":"elisa", "testo": "questo blog è molto interessante"},
.....
]
"commenti_count": 86,
"commenti_pagine": 5
}
Apriamo la nostra pagina web contenente il post, e verranno subito visualizzati i primi 20 commenti, senza dover fare altre query. A quel punto se l'utente fosse curioso di vedere i commenti succesivi, nella paginazione che andremo a creare, cliccherà sulla pagina successiva, e solo in quel momento andremo a fare una nuova query per estrarre i 20 commenti successivi.
La collezione di questi commenti, ad esempio, conterrà documenti come questo, dove c'è, oltre al suo id, il rifermento all'id del post che l'ha generato, i commenti, e anche il numero di pagina e il numero di commenti contenuti in questa pagina
{
"_id" : ObjectId("5f870ed601f71f5fe8651deb"),
"post_id" : ObjectId("5099803df3f4948bd2f98391"),
"count": 20,
"page": 2,
"commenti":[
{"nome":"maria", "testo": "come creo una classe?"},
{"nome":"stefano", "testo": "non sono d'accordo"},
.....
]
}
In alternativa all'embedding, potremmo utilizzare delle reference nei commenti, cioè al posto di indicare le "chiavi/valori" di tutti i commenti utilizziamo delle referenze, cioè gli "_id" di ogni singolo commento che andremo a salvare in una collection separata.
Questa è un documento della collection "blog", con tre commenti che rimandano a tre documenti di una collection separata "commenti"
{
"_id" : ObjectId("5099803df3f4948bd2f98391")
"titolo":"Parliamo del linguaggio PHP",
"testo":"Prova prova prova prova prova ....",
"autore":"Mario Rossi",
"commenti":[
ObjectId("5f870916a6ea36126836984a"),
ObjectId("5f87092057a439174ad993fe"),
ObjectId("5f87092bc69be61162358aa7")
]
}
E questo è un documento della collection "commenti" (notiamo il riferimento all' ObjectId del post contenuto nella collection blog)
{
"_id" : ObjectId("5f870916a6ea36126836984a"),
"post_id": ObjectId("5099803df3f4948bd2f98391"),
"nome":"elisa",
"testo":"questo blog è molto interessante"
}
L'utilizzo di una reference tuttavia è sconsigliato per motivi di performance perchè dobbiamo eseguire una query per ogni singolo documento, ottenere così la lista di tutti gli ID dei commenti, e a questo punto fare una query per ogni commento.
Connessione al database
La connessione a MongoDB si instaura tramite client, una Mongo shell, che permette l’accesso tramite riga di comando, ed è un interprete javascript per cui possiamo utilizzare codice javascript.
Tuttavia, utilizzando appositi driver, è possibile utilizzarlo dalla nostra appicazione (sito web) con quasi tutti i linguaggi di programmazione come ad esempio PHP, NodeJS, Python, Java.
MongoDB utilizza il linguaggio JSON solo quando deve mostrarci i dati nella shell e per interagire con "noi" programmatori, ma internamente in realtà salva i dati in forma binaria, convertendoli in BSON (Bynary JSON), e tutto questo avviene in automatico, per cui voi non dovete far nulla e quindi non dovete conoscere BSON. Sappiate solo che il BSON è la rappresentazione binaria del JSON.
MongoDB in Linux
Finalmente siamo giunti all'installazione di MongoDB "Community Edition", attualmente alla versione 4.4, in una distribuzione Linux CentOS 8.
Per Centos 6 e 7, e le altre principali distribuzioni Linux, si rimanda alla documentazione ufficiale di Mongo.
Repository MongoDB
MongoDB non è disponibile nella repository di CentOS 8, ma esiste la repo ufficiale di MongoDB, che dobbiamo abilitare e solo successivamente potremo installare il pacchetto.
Utilizzando l'editor vi, o quello che preferite, creiamo un nuovo file chiamato "mongodb-org-4.4.repo" all'interno della directory "/etc/yum.repos.d".
# vi /etc/yum.repos.d/mongodb-org-4.4.repo
Nel nome del file abbiamo indicato la versione che stiamo installando, la 4.4.
Al suo interno scriviamo e salviamo questo codice
[mongodb-org-4.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc
Quello che abbiamo fatto è aggiungere, ai repo di Centos, questo repo di MongoDB.
A questo punto possiamo procedere all'installazione del pacchetto.
Installazione MongoDB
Tramite lo strumento yum, o dnf, procediamo con l'installazione.
# yum install mongodb-org
Con questa installazione, scarichiamo vari pacchetti tra cui:
- mongodb-org-server: è il server database (è il demone "mongod")
- mongodb-org-shell: è l'interfaccia di amministrazione da riga di comando
- mongodb-org-tools: sono vari strumenti per l'importazione ed esportazione dei dati, statistiche e altre utility
- mongodb-org-mongos: utilizzato per installazioni di tipo "sharding" cioè quando andiamo a distribuire i dati su più server. (è il demone "mongos")
Nota: questi pacchetti, volendo, avresti anche potuto scaricarli in formato RPM dalla pagina di download del sito Mongo, e poi installarli manualmente.
Default path e file di configurazione
L'installazione crea automaticamente due directory sul nostro server:
- /var/lib/mongo: dove verranno i dati del nostro database
- /var/log/mongodb: dove verranno i log
Viene inoltre creato il file di configurazione chiamato "mongod.conf" nella directory "etc". Questo file ha un formato YAML è quindi importante rispettare la formattazione. Se sei curioso, aprilo e guarda il suo contenuto
Avvio del database
Possiamo finalmente avviare il nostro server MongoDB, con il demone "mongod"
# systemctl enable mongod --now
Con questo comando abbiamo, nello stesso momento, abiliato mongo in modo che si avvi automaticamente ad ogni riavvio del server, e lo abbiamo avviato con "--now"
Per verificare che effettivamente sia avviato, utilizziamo "systemctl status"
# systemctl status mongod
● mongod.service - MongoDB Database Server
Loaded: loaded (/usr/lib/systemd/system/mongod.service; enabled; vendor preset: disabled)
Active: active (running) since Wed 2020-10-14 18:19:53 CEST; 13s ago
Docs: https://docs.mongodb.org/manual
Process: 9720 ExecStart=/usr/bin/mongod $OPTIONS (code=exited, status=0/SUCCESS)
Process: 9717 ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb (code=exited, status=0/SUCCESS)
Process: 9716 ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb (code=exited, status=0/SUCCESS)
Process: 9713 ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb (code=exited, status=0/SUCCESS)
Main PID: 9722 (mongod)
Memory: 65.3M
CGroup: /system.slice/mongod.service
└─9722 /usr/bin/mongod -f /etc/mongod.conf
Oct 14 18:19:52 vas100 systemd[1]: Starting MongoDB Database Server...
Oct 14 18:19:52 vas100 mongod[9720]: about to fork child process, waiting until server is ready for connections.
Oct 14 18:19:52 vas100 mongod[9720]: forked process: 9722
Oct 14 18:19:53 vas100 mongod[9720]: child process started successfully, parent exiting
Oct 14 18:19:53 vas100 systemd[1]: Started MongoDB Database Server.
Così, per stoppare MongoDB
systemctl stop mongod
e per riavviarlo
systemctl restart mongod
Primo utilizzo della shell
Proviamo ad utilizzare la shell amministrativa di Mongo, tramite il comando "mongo", per verificare la versione di Mongo installata. Utilizziamo l'opzione "--version"
# mongo --version
MongoDB shell version v4.4.1
Build Info: {
"version": "4.4.1",
"gitVersion": "ad91a93a5a31e175f5cbf8c69561e788bbc55ce1",
"openSSLVersion": "OpenSSL 1.1.1c FIPS 28 May 2019",
"modules": [],
"allocator": "tcmalloc",
"environment": {
"distmod": "rhel80",
"distarch": "x86_64",
"target_arch": "x86_64"
}
}
Prova adesso a utilizzare l'opzione "--nodb" che ti consente di usare la shell senza collegarti ad un database
# mongo --nodb
MongoDB shell version v4.4.1
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
https://docs.mongodb.com/
Questions? Try the MongoDB Developer Community Forums
https://community.mongodb.com
>
Bene, adesso la shell è in attesa di istruzioni.
Essendo un interprete javascript possiamo indicare una qualunque istruzione javascript, ad esempio creriamo una variabile "nome", e la stampiamo a video.
MongoDB shell version v4.4.1
> var nome ="giulio";
> print (nome);
giulio
>
Usciamo dalla shell utlizzando il comando quit() o con exit
> exit
In questo primo test non ci siamo effettivamente collegati al database, facciamolo adesso. E' quindi obbligatorio che il server mongd sia attivo.
Digita semplicemente "mongo" e saremmo collegati al server locale (perchè Mongo è installato su questo stesso server) 127.0.0.1, con porta 27017 (di default)
# mongo
MongoDB shell version v4.4.1
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("d333f373-0364-4ca9-ada2-d5f611934ba6") }
MongoDB server version: 4.4.1
---
The server generated these startup warnings when booting:
2020-10-14T18:19:52.974+02:00: ***** SERVER RESTARTED *****
2020-10-14T18:19:53.338+02:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
2020-10-14T18:19:53.338+02:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
---
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).
The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
>
La shell è in attesa di istruzioni.
Primi comandi da shell
Per sapere a quale database siamo connessi digitiamo "db" e la shell risponderà con "test": questo è il database di default in cui Mongo di fa accedere.
> db
test
Ma attenzione: in realtà questo database non esiste o meglio, non esiste ancora. Infatti un database esiste veramente solo nel momento in cui andiamo a creare una collection (tabella).
Per dimostrartelo, prova a spostarti di database, usando il comando "use" seguito dal nome del database, ad esempio "demo" ... che non esiste
> use demo
switched to db demo
Anche se non esiste ancora, così come non esiste il database "test", stiamo usando questo database: questo database verrà effettivamente creato sono nel momento in cui lo andremo ad utilizzare attraverso la creazione di collections (tabelle) e documenti (records).
Cerchiamo in questo database demo, i records contenuti in una collection (tabella) chiamata "giocatori"... che non esiste. Con la funzione find andiamo ad estrarre tutti i records
> db.giocatori.find()
db: è un oggetto all'interno della nostra shell ed identifica il database in uso, nel nostro caso "demo"
giocatori: è una collection, che ancora non esiste (una tabella)
find(): è il comando che equivale ad una SELECT per estrarre i dati
Possiamo leggerlo così "vai a prendere il database in uso, cioè demo, considera la collection giocatori, e cerca tutti i documenti che ci sono al suo interno".
Lanciando questo comando non succede nulla perchè non esiste ancora ne la collection (tabella) ne i suoi documenti (records).
Proviamo a creare il primo documento nella collection giocatori, con il comando insert.
Inseriamo il giocatore "ronaldo" con tutti campi che avevamo previsto all'inizio della nostra spiegazione, quindi il nome, l'età, e le competizione vinte, indicate in un array (parentesi quadre!)
> db.giocatori.insert(
{
"nome":"ronaldo",
"eta": 34,
"vittorie": [
{"anno":"2002", "competizione":"Supercoppa portoghese"},
{"anno":"2003", "competizione":"Coppa d'Inghilterra"},
{"anno":"2019", "competizione":"Serie A"},
]
}
)
Il risultato sarà il seguente
WriteResult({ "nInserted" : 1 })
>
Il documento (record) è stato inserito e il database creato.
Infatti, con il comando "show dbs" posso vedere tutti database presenti
> show dbs
admin 0.000GB
config 0.000GB
demo 0.000GB
local 0.000GB
Possiamo vedere il nostro database "demo" ed altri database di sistema già presenti. Non c'è il database "test".
Possiamo anche conoscere la lista delle collections presenti nel database in uso, con il comando "show collections"
> show collections
giocatori
Adesso che il database "demo" è creato, con la collection "giocatori", ed un documento al suo interno, riproviamo con il comando "find" e verrà visualizzato il nostro documento
> db.giocatori.find()
{ "_id" : ObjectId("5f86e7adb8927708451222bb"), "nome" : "ronaldo", "eta" : 34, "vittorie" : [ { "anno" : "2002", "competizione" : "Supercoppa portoghese" }, { "anno" : "2003", "competizione" : "Coppa d'Inghilterra" }, { "anno" : "2019", "competizione" : "Serie A" } ] }
>
Possiamo vedere che, assieme a tutti i campi che abbiamo creato, ne è stato aggiunto uno chiamato "_id": è un attributo speciale, di tipo "ObjectId": è un indice e deve essere sempre presente ed in sua assenza viene creato in automatico da Mongo.
Creiamo un secondo documento
> db.giocatori.insert(
{
"nome":"ibrahimovic",
"eta": 38,
"vittorie": [
{"anno":"2007", "competizione":"Serie A"},
{"anno":"2009", "competizione":"Supercoppa UEFA"},
{"anno":"2017", "competizione":"Europa League"}
]
}
)
Ripetiamo la ricerca
{ "_id" : ObjectId("5f86e7adb8927708451222bb"), "nome" : "ronaldo", "eta" : 34, "vittorie" : [ { "anno" : "2002", "competizione" : "Supercoppa portoghese" }, { "anno" : "2003", "competizione" : "Coppa d'Inghilterra" }, { "anno" : "2019", "competizione" : "Serie A" } ] }
{ "_id" : ObjectId("5f86e98bb8927708451222bc"), "nome" : "ibrahimovic", "eta" : 38, "vittorie" : [ { "anno" : "2007", "competizione" : "Serie A" }, { "anno" : "2009", "competizione" : "Supercoppa UEFA" }, { "anno" : "2017", "competizione" : "Europa League" } ] }
Adesso che abbiamo due documenti possiamo effettuare una ricerca più approfondita.
Nel find, infatti, possiamo mettere delle condizioni json: ad esempio vogliamo sapere quali sono i giocatori che hanno 34 anni, per cui cerchiamo nella chiave "eta" il valore "34".
> db.giocatori.find( {"eta":34} )
Il risultato sarà
{ "_id" : ObjectId("5f86e7adb8927708451222bb"), "nome" : "ronaldo", "eta" : 34, "vittorie" : [ { "anno" : "2002", "competizione" : "Supercoppa portoghese" }, { "anno" : "2003", "competizione" : "Coppa d'Inghilterra" }, { "anno" : "2019", "competizione" : "Serie A" } ] }
Per leggere meglio la risposta aggiungiamo .pretty() dopo il .find()
> db.giocatori.find( {"eta":34} ).pretty()
La risposta sarà formattata in questo modo
{
"_id" : ObjectId("5f86e7adb8927708451222bb"),
"nome" : "ronaldo",
"eta" : 34,
"vittorie" : [
{
"anno" : "2002",
"competizione" : "Supercoppa portoghese"
},
{
"anno" : "2003",
"competizione" : "Coppa d'Inghilterra"
},
{
"anno" : "2019",
"competizione" : "Serie A"
}
]
}
Se avessimo avuto più match ovviamente sarebbero stati estratti tutti i documenti.
Per estrarre invece un solo documento utilizziamo, findOne, al posto di find. Con findOne non puoi usare pretty, tuttavua otterrai comunque il risultato ben formattato.
> db.giocatori.findOne( {"eta":34} )
Vediamo adesso come aggiungere un campo.
Iniziamo con il cercare il documento con uno specifico id: ObjectId("5f86e7adb8927708451222bb").
> db.giocatori.findOne( {"_id" : ObjectId("5f86e7adb8927708451222bb")} )
Essendo la shell un interprete javascript, creiamo in javascript una variabile x con valore questa estrazione
> var x = db.giocatori.findOne( {"_id" : ObjectId("5f86e7adb8927708451222bb")} )
Nella variabile x abbiamo il nostro documento, infatti se digitiamo x avremo:
> x
{
"_id" : ObjectId("5f86e7adb8927708451222bb"),
"nome" : "ronaldo",
"eta" : 34,
"vittorie" : [
{
"anno" : "2002",
"competizione" : "Supercoppa portoghese"
},
{
"anno" : "2003",
"competizione" : "Coppa d'Inghilterra"
},
{
"anno" : "2019",
"competizione" : "Serie A"
}
]
}
Adesso che x è il nostro documento (è un oggetto di tipo json) possiamo modificarlo ed aggiungere degli attributi, ad esempio aggiungiamo la chiave "anno di nascita", in questo modo
> x.year = 1992
Se adesso visualizzi il docmento vedrai che è stata aggiunta la coppia chiave / valore
> x
{
"_id" : ObjectId("5f86e7adb8927708451222bb"),
"nome" : "ronaldo",
"eta" : 34,
"vittorie" : [
{
"anno" : "2002",
"competizione" : "Supercoppa portoghese"
},
{
"anno" : "2003",
"competizione" : "Coppa d'Inghilterra"
},
{
"anno" : "2019",
"competizione" : "Serie A"
}
],
"year" : 1992
}
Questa modifica non è ancora stata effettivamente salvata nel database. Per salvarla utilizziamo la funzione save().
> db.giocatori.save(x)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
La funzione save() in realtà non viene molto usata, è una sorta di scorciatoia sia per l'update che per l'insert, che vedremo in un secondo momento.
Se provi a digitare db.giocatori.save, senza argomenti, la shell ti mostrerà il codice della funzione con cui viene eseguito l'insert o l'update
> db.giocatori.save
function(obj, opts) {
if (obj == null)
throw Error("can't save a null");
if (typeof (obj) == "number" || typeof (obj) == "string")
throw Error("can't save a number or string");
if (typeof (obj._id) == "undefined") {
obj._id = new ObjectId();
return this.insert(obj, opts);
} else {
return this.update({_id: obj._id}, obj, Object.merge({upsert: true}, opts));
}
}
Questa funzione verifica se l'oggetto json (la variabile x) possiede o meno l'attributo "_id": se lo possiede fa un update, in caso contrario fa una insert.
Per conoscere tutti i comandi disponibili, digita "help"
> help
db.help() help on db methods
db.mycoll.help() help on collection methods
sh.help() sharding helpers
rs.help() replica set helpers
help admin administrative help
help connect connecting to a db help
help keys key shortcuts
help misc misc things to know
help mr mapreduce
show dbs show database names
show collections show collections in current database
show users show users in current database
show profile show most recent system.profile entries with time >= 1ms
show logs show the accessible logger names
show log [name] prints out the last segment of log in memory, 'global' is default
use <db_name> set current database
db.mycoll.find() list objects in collection mycoll
db.mycoll.find( { a : 1 } ) list objects in mycoll where a == 1
it result of the last line evaluated; use to further iterate
DBQuery.shellBatchSize = x set default number of items to display on shell
exit quit the mongo shell
Nei prossimi articoli vedremo MongoDB in azione in tutte le operazioni CRUD (create, read, update, delete).
Stay tuned!