NoSQL
Una base de dades NoSQL (sovint interpretat com a Not only SQL i significa 'No només SQL') proporciona un mecanisme per emmagatzemar i recuperar dades que es modela mitjançant relacions tabulars diferents a les utilitzades en les bases de dades relacionals. Aquest canvi de model està motivat per la simplicitat de disseny, l'escalabilitat horitzontal i un major control de la disponibilitat. Les estructures de dades utilitzades per les bases de dades NoSQL (p. ex. clau-valor, graf i document) difereixen de les relacionals, fet que possibilita que algunes operacions siguin més ràpides en les NoSQL que en les relacionals. L'elecció d'una o altra base de dades NoSQL depèn del problema a solucionar.
L'ús de bases de dades NoSQL ha augmentat notablement en sistemes Big Data i en aplicacions web a temps real. Als sistemes NoSQL se'ls anomena també "No només SQL" per emfatitzar que aquest tipus d'eines poden admetre llenguatges d'interrogació estructurats (SQL). Molts gestors NoSQL comprometen la consistència a favor de disponibilitat i la tolerància a la partició. Les reticències principals a adoptar sistemes NoSQL són l'ús de llenguatges d'interrogació de baix nivell, la manca d'interfícies estandarditzades i les grans inversions prèvies fetes en les bases de dades SQL existents. Gran part dels gestors NoSQL no compleixen completament les propietats ACID, i així doncs, no garanteixen transaccions realment fiables.
MongoDB
MongoDB és defineix com una base de dades documental. És programari lliure i està escrita en C++. Segurament és el principal gestor de bases de dades NoSQL del mercat.
Ens ofereix:
- Alt rendiment: les dades es guarden sovint en el mateix (o molt similar) format amb que les manipulen els programes. A més, MongoDB ofereix un sistema d'indexació molt flexible per accelerar les consultes.
- Alta disponibilitat: MongoDB ofereix mecanismes de replicació de les dades amb recuperació automàtica de caigudes i redundància de dades.
- Escalat automàtic: ens ofereix un mecanisme de distribució de dades automatitzat (sharding) que ens permet que les nostres dades creixin sense limitacions.
A MongoDB, els registres es coneixen com a documents, o també com a objectes. Un document és bàsicament un conjunt de parells clau-valor, en format JSON (JavaScript Object Notation), un format lleuger per l'intercanvi de dades.
SQL vs MongoDB
A continuació es pot veure l'equivalència entre els conceptes utilitzats a SQL i MongoDB.
JSON i BSON
Exemple de JSON:
{
"name" : "John Brown",
"salary" : 350000,
"type" : "FT",
"address" : {
"area" : "Noida",
"city" : "Delhi"
},
"courses" : [
{
"name" : "java",
"type" : "technical"
},
{
"name" : "dotnet",
"type" : "technical"
},
{
"name" : "hadoop",
"type" : "technical"
}
]
}
JSON (acrònim de JavaScript Object Notation) és un estàndard obert basat en text dissenyat per a intercanvi de dades llegible per humans. Deriva del llenguatge script JavaScript, per a representar estructures de dades simples i llistes associatives, anomenades objectes. Malgrat la seva relació amb el JavaScript, té implementacions per a gran part dels llenguatges de programació. Douglas Crockford va especificar i popularitzar el format JSON,[1] i es descriu a l'[RFC:4627 RFC:4627]. El tipus MIME del JSON és application/json
. L'extensió de fitxer és .json
.
El format JSON s'utilitza habitualment per serialitzar i transmetre dades estructurades en una connexió de xarxa. S'utilitza principalment per intercanviar dades entre un servidor i una aplicació web, sent una alternativa a l'XML.
BSON / biːsən / és un format d'intercanvi d'informació informàtic utilitzat principalment com a format d'emmagatzematge de dades i de transferència de xarxa a la base de dades MongoDB. És una forma binària per representar estructures de dades simples, matrius associatives (anomenats objectes o documents en MongoDB), i diversos tipus de dades d'interès específic per a MongoDB. El nom "BSON" es basa en el terme JSON i significa "JSON binari".
Instal.lació
El manual es troba aquí, i la secció d'instal.lació aquí.
Pots descarregar el MongoDB Community Edition des de la pàgina de descàrrega.
Convé afegir la carpeta bin de la instal.lació al PATH.
A Windows hi ha dues opcions:
- Amb servei.
- Sense servei: cal iniciar bin/mongod i que existeixi una carpeta /data/db i /data/log (a la mateixa carpeta que la instal.lació).
Veure la base de dades actual:
> db
Sel.leccionar una base de dades:
> use <database>
Per mostrar totes les bases de dades existents i les col.leccions existents de la base de dades sel.leccionada:
> show dbs
> show collections
Crea una base de dades anomenada "testdb", una col.lecció "persones" i insereix un document:
> use testdb
> db.persones.insertOne( { nom: 'Pere', edat: 23 } );
{
"acknowledged" : true,
"insertedId" : ObjectId("5bf52138e44e1fdc9edd15e5")
}
MongoDB torna un id que es genera automàticament per cada document.
Per trobar els registres creats:
> db.persones.find({})
{ "_id" : ObjectId("5bf52138e44e1fdc9edd15e5"), "nom" : "Pere", "edat" : 23 }
{ "_id" : ObjectId("5bf5219de44e1fdc9edd15e6"), "nom" : "Joan", "edat" : 21 }
{ "_id" : ObjectId("5bf521b0e44e1fdc9edd15e7"), "nom" : "Lluís", "edat" : 28 }
{ "_id" : ObjectId("5bf52255e44e1fdc9edd15e8"), "nom" : "Jordi", "edat" : 35 }
Afegint una condició:
> db.persones.find({ edat: 21})
{ "_id" : ObjectId("5bf5219de44e1fdc9edd15e6"), "nom" : "Joan", "edat" : 21 }
Trobar per _id:
> db.persones.find( {_id: ObjectId("5bf521b0e44e1fdc9edd15e7")} )
{ "_id" : ObjectId("5bf521b0e44e1fdc9edd15e7"), "nom" : "Lluís", "edat" : 28 }
Actualitzar un document (el primer que troba):
> db.persones.updateOne({ nom: "Jordi" }, { $set: {edat: 36} })
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
Incrementar un camp a molts registres:
> db.persones.updateMany({}, { $inc: { edat: NumberInt(1) } })
{ "acknowledged" : true, "matchedCount" : 4, "modifiedCount" : 4 }
La opció per esborrar un camp és $unset.
Reemplaçar un document (excepte el _id):
> db.persones.replaceOne({ nom: "Lluís" }, { nom: "Maria", edat: 36 })
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
Esborrar un document (el primer que troba: no troba cap):
> db.persones.deleteOne({ edat: 13 })
{ "acknowledged" : true, "deletedCount" : 0 }
Esborrar molts documents (no troba cap):
> db.persones.deleteMany({ edat: 15 })
{ "acknowledged" : true, "deletedCount" : 0 }
Sortir:
exit
Arrays
Els arrays poden formar part d'un document, com per exemple "mitjans":
{ "_id" : ObjectId("5bf684eff884d83e4c4a8cfa"), "nom" : "Joan", "edat" : 22, "mitjans" : [ "tv", "mobil" ] }
Podem filtrar la cerca pel contingut de l'array. La primera comanda busca exactament documents amb els dos mitjans; la segona, que al menys continguin els dos; la tercera, que contingui un.
> db.mitjans.find({ mitjans: ["mobil", "portatil"] })
> db.mitjans.find({ mitjans: { $all: ["mobil", "portatil"] } })
> db.mitjans.find({ mitjans: "tv" })
Podem afegir contingut a un array (push) o treure'l (pull). També podem afegir només si no existeix (addToSet).
> db.persones.updateOne({}, {$push: {mitjans: "tv"}})
> db.persones.updateOne({}, {$pull: {mitjans: "tv"}})
Condicions combinades
Es poden combinar condicions per utilitzar-les a les cerques (find) o bé a les condicions per fer un update o un delete.
Les condicions es troben explicades aquí.
Per exemple, per buscar amb l'operador AND aquells que tinguin el mitjà "tv" i siguin menors de 30 anys:
> db.mitjans.find( { $and: [ {mitjans: "tv"}, {edat: { $lt: 30}} ]} )
O trobar els que no tinguin "mobil":
> db.persones.find({ mitjans: { $not: { $eq: "mobil"} } })
Importar dades
Es poden importar dades des d'un arxiu de text que tingui un format de text com aquest:
{"mitjans":["sobretaula"],"nom":"Amya","edat":37}
{"mitjans":["tauleta","mobil","portatil"],"nom":"Abdul","edat":20}
{"mitjans":["tauleta","mobil","portatil"],"nom":"Jordyn","edat":16}
{"mitjans":["tauleta","mobil","portatil"],"nom":"Annie","edat":25}
L'eina és mongoimport. Aquest és un exemple d'ús, per importar un arxiu "mitjans.json" a la base de dades "testdb" i la col.lecció "mitjans":
$ mongoimport --db testdb --collection mitjans mitjans.json
La documentació del driver es troba aquí.
Des d'aquesta pàgina (MongoDB Driver Sync), Es poden descarregar manualment els tres jars que es necessiten:
Per defecte, MongoDB no té control d'accés.
Així es podria accedir a la base de dades "testdb" del teu ordinador:
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("testdb");
Per defecte, MongoDB utilitza el port 27017.
Si es vol accedir a una col.lecció, cal fer-ho així:
MongoCollection<Document> collection = database.getCollection("persones");
Tot l'accés als documents que hi ha a les col.leccions es fa mitjançant la classe Document
.
Aquesta classe és realment un mapa, però té el mètode append per a facil.litar l'encadenació de crides al put:
public Document append(final String key, final Object value) {
documentAsMap.put(key, value);
return this;
}
Per tant, es poden fer coses com:
Document doc = new Document().append("nom", "John").append("edat", 26);
A partir d'aquest objecte, es pot afegir a la col.lecció així:
collection.insertOne(doc);
Per fer una cerca i iterar sobre els resultats, es pot fer:
MongoCursor<Document> cursor = collection.find().iterator();
while (cursor.hasNext()) {
Document doc = cursor.next();
System.out.println(doc);
}
cursor.close();
Cal sempre tancar el cursor. Com és una classe que implementa AutoCloseable, es pot fer un try-with-resources.
Per crear una condició, cal passar un objecte Bson
al mètode collection.find()
. Per exemple, per trobar les persones amb més de 30 anys, i fer-ho amb un try-with-resources:
Bson condicio = Filters.gt("edat", 30);
try (MongoCursor<Document> cursor = collection.find(condicio).iterator()) {
while (cursor.hasNext()) {
Document doc = cursor.next();
System.out.println(doc);
}
}
La condició per cercar per ID seria aquesta (si busquem per l'id 5bf5716d7a8847dc909284e9):
Bspm condicio = Filters.eq("_id", new ObjectId("5bf5716d7a8847dc909284e9"));
Per fer updates:
UpdateResult uResult = collection.updateOne(Filters.eq("nom", "Maria"), Updates.set("edat", 34));
System.out.println(uResult); // AcknowledgedUpdateResult{matchedCount=1, modifiedCount=1, upsertedId=null}
Els sets es poden combinar fer Updates.combine(...)
. També es poden utilitzar les següents operacions per fer updates:
Updates.push(camp, contingut)
per afegir un element a un array.Updates.pull(camp, contingut)
per esborrar un element d'un array.Updates.addToSet(camp, contingut)
per afegir un element a un array, si no existeix.
Per fer deletes:
DeleteResult dResult = collection.deleteOne(Filters.eq("nom", "Mario"));
System.out.println(dResult); // AcknowledgedDeleteResult{deletedCount=0}
Per accedir a arrays dins d'un document només cal obtenir una List del tipus que contingui. Per exemple, si l'array "mitjans" conté Strings:
List<String> mitjans = (List<String>) document.get("mitjans");
TO DO: sorts, projections, read/write concerns, aggregation.