Omet navegació

4.2.2 - Operacions bàsiques

En aquest punt anem a veure les operacions més bàsiques, per a poder treballar sobre exemples pràctics, i així disposar ja d'unes dades inicials per a practicar.

Inserció elemental

La funció insert afegirà documents a una col·lecció. En el paràmetre posem el document directament, o una variable que continga el document. Si la col·lecció no existia, la crearà i després afegirà el document. En la següent sentència estem treballant sobre la col·lecció exemple, que segurament ja existirà de quan vam la pregunta 3.1 d'instal·lació de MongoDB, que per a provar vam inserir un document. Però si no existia, la crearà sense problemes.

> db.exemple.insert({ msg2 : "Com va la cosa?"})
WriteResult({ "nInserted" : 1 })

Acabem d'inserir un nou document, i així ens ho avisa ( { "nInserted" : 1 } , s'ha inserit un document). Automàticament haurà creat un element _id de tipus ObjectId, ja que li fa falta per a identificar el document entre tots els altres de la col·lecció.

I en aquest exemple ens guardem el document en la variable doc, i després l'inserim

> doc = { msg3 : "Per ací no ens podem queixar ..."}
{ "msg3" : "Per ací no ens podem queixar ..." }
> db.exemple.insert(doc)
WriteResult({ "nInserted" : 1 })

També ens indica que ha inserit un document. I haurà creat també el camp _id com veurem en el següent punt

Lectura

Tenim dues funcions per a recuperar informació: find i findOne.

  • find() : recuperarà tots els documents de la col·lecció, encara que podrem posar criteris per a que ens torne tots els documents que acomplesquen aquestos criteris (ho veurem més avant).
  • findOne() : només tornarà un document, en principi el primer. Pot ser sobre tots els documents (i per tant seria el primer document), o posar una condició, i tornaria el primer que acomplirà la condició.

Exemple de find():

> db.exemple.find()
{ "_id" : ObjectId("56ce310bc61e04ba81def50b"), "msg" : "Hola, què tal?" }
{ "_id" : ObjectId("56ce31f6c61e04ba81def50c"), "msg2" : "Com va la cosa?" }
{ "_id" : ObjectId("56ce3237c61e04ba81def50d"), "msg3" : "Per ací no ens podem queixar ..." }
>

Exemple de findOne():

> db.exemple.findOne()
{ "_id" : ObjectId("56ce310bc61e04ba81def50b"), "msg" : "Hola, què tal?" }
>

En tots els casos podem comprovar que és cert el que veníem afirmant, que ha creat automàticament l'element _id per a cada document guardat. Evidentment, cadascú de nosaltres tindrà una valors diferents.

Inserció especificant el id

Ara que ja sabem consultar els document de la col·lecció amb find() anem a continuar les insercions de documents, per veure les possibilitats que tenim.

En els document que hem inserit fins el moment, no hem especificat el camp _id, i Mongo l'ha generat automàticament de tipus ObjectId.

Però nosaltres podrem posar aquest camp _id amb el valor que vulguem. Això sí, haurem d'estar segurs que aquest valor no l'agafa cap altre dcument de la col·lecció, o ens donarà un error.

Així per exemple anem a inserir la informació d'uns alumnes. Els posarem en una col·lecció nova anomenada alumnes, i els intentarem posar un _id personal. Per exemple posarem els números 51, 52, 53, ...

> db.alumnes.insert ({_id: 51 , nom: "Rebeca" , cognoms: "Martí Peral"})
WriteResult({ "nInserted" : 1 })

Ha anat bé, i si mirem els documents que tenim en la col·lecció, comprovarem que ens ha respectat el _id:

> db.alumnes.find()
{ "_id" : 51, "nom" : "Rebeca", "cognoms" : "Martí Peral" }
>

Però si intentem inserir un altre document amb el mateix _id (51), ens donarà error:

> db.alumnes.insert ({_id: 51 , nom: "Raquel" , cognoms: "Gomis Arnau"})
WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "E11000 duplicate key error collection: test.alumnes index: _id_ dup key: { : 51.0 }"
    }
})
>

Ens avisa que estem duplicant la clau principal , és a dir l'identificador.

Inserció múltiple

Quan els documents que volem inserir són senzills, podem inserir més d'un a la vegada, posant dis del insert() un array amb tots els elements. En el següent exemple creem uns quants nombres primers en la col·lecció del mateix nom:

> db.nombresprimers.insert( [ {_id:2} , {_id:3} , {_id:5} , {_id:7} , {_id:11} , {_id:13} , {_id:17} , {_id:19} ] )
BulkWriteResult({
    "writeErrors" : [ ],
    "writeConcernErrors" : [ ],
    "nInserted" : 8,
    "nUpserted" : 0,
    "nMatched" : 0,
    "nModified" : 0,
    "nRemoved" : 0,
    "upserted" : [ ]
})
>

Ens avisa que ha fet 8 insercions, i ací els tenim:

> db.nombresprimers.find()
{ "_id" : 2 }
{ "_id" : 3 }
{ "_id" : 5 }
{ "_id" : 7 }
{ "_id" : 11 }
{ "_id" : 13 }
{ "_id" : 17 }
{ "_id" : 19 }
>

Esborrat

Per a esborrar un document d 'una col·lecció utilitzarem la funció remove, passant-li com a paràmetre la condició del document o documents a esborrar.

> db.nombresprimers.remove( {"_id" : 19} )
WriteResult({ "nRemoved" : 1 })
>

Ens avisa que ha esborrat un document.

La condició no cal que siga sobre el camp _id. Pot ser sobre qualsevol camp, i esborrarà tots els que coincideixen.

> db.exemple.remove( {"msg3" : "Per ací no ens podem queixar ..."} )
WriteResult({ "nRemoved" : 1 })
>

També tenim la possibilitat d'esborrar tota una col·lecció amb la funció drop(). Pareu atenció perquè és molt senzilla d'eliminar, i per tant, potencialment molt perillosa.

> db.nombresprimers.drop()
true
>

Actualització

La funció update servirà per a actualitzar un document ja guardat. Tindrà dos paràmetres:

  • El primer paràmetre serà la condició per a trobar el document que s'ha d'actualitzar.
  • El segon paràmetre serà el nou document que substituirà l'anterior

Per exemple, si mirem les dades actuals:

> db.exemple.find()
{ "_id" : ObjectId("56ce310bc61e04ba81def50b"), "msg" : "Hola, què tal?" }
{ "_id" : ObjectId("56ce31f6c61e04ba81def50c"), "msg2" : "Com va la cosa?" }

Podem comprovar el contingut del segon document, el que te msg2. Anem a modificar-lo: en el primer paràmetre posem condició de búsqueda (només hi haurà un) i en el segon posem el nou document que substituirà l'anterior

> db.exemple.update( {msg2:"Com va la cosa?"} , {msg2:"Què? Com va la cosa?"} )
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

Observeu que la contestació del update() és que ha fet match (hi ha hagut coincidència) amb un document, i que ha modificat un. Si no en troba cap, no donarà error, senzillament dirà que ha fet match amb 0 documents, i que ha modificat 0 documents. Mirem com efectivament ha canviat el segon document

> db.exemple.find()
{ "_id" : ObjectId("56ce310bc61e04ba81def50b"), "msg" : "Hola, què tal?" }
{ "_id" : ObjectId("56ce31f6c61e04ba81def50c"), "msg2" : "Què? Com va la cosa?" }

Ens vindran molt bé les variables per a les actualitzacions, ja que en moltes ocasions serà modificar lleugerament el document, canviant o afegint algun element. Ho podrem fer còmodament amb la variable: primer guardem el document a modificar en una variable; després modifiquem la variable; i per últim fem l'operació d'actualització. Evidentment si tenim alguna variable amb el contingut del document ens podríem estalviar el primer pas.

> doc1 = db.exemple.findOne()
{ "_id" : ObjectId("56ce310bc61e04ba81def50b"), "msg" : "Hola, què tal?" }

> doc1.titol = "Missatge 1"
Missatge 1

> db.exemple.update( {msg:"Hola, què tal?"} , doc1)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.exemple.findOne()
{
    "_id" : ObjectId("56ce310bc61e04ba81def50b"),
    "msg" : "Hola, què tal?",
    "titol" : "Missatge 1"
}
>

Funció Save

Hem vist la manera d'inserir nous documents amb insert() i d'actualitzar documents existents amb update(). Però si intentem inserir un document ja existent (la manera de saber-ho és pel camp _id) ens donarà error. I si intentem actualitzar un document no existent, no donarà error, però no actualitzarà res.

La funció save() és una barreja dels dos: si el document que anem a salvar ja existeix, doncs el modificarà, i si no existeix el crearà.

Provem-ho amb un exemple, i aprofitem-nos que en la variable doc1 tenim el contingut d'un document. Fem una modificació, per exemple afegint el camp destinatari:

> doc1.destinatari = "Ferran"
Ferran

> doc1
{
    "_id" : ObjectId("56ce310bc61e04ba81def50b"),
    "msg" : "Hola, què tal?",
    "titol" : "Missatge 1",
    "destinatari" : "Ferran"
}

Anem a guardar-lo amb save():

> db.exemple.save(doc1)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

Ja ens avisa qiue com ha trobat el document ("nMatched : 1") ha modificat un. Efectivament, mirem com ha modificat el document existent:

> db.exemple.find()
{ "_id" : ObjectId("56ce310bc61e04ba81def50b"), "msg" : "Hola, què tal?", "titol" : "Missatge 1", "destinatari" : "Ferran" }
{ "_id" : ObjectId("56ce31f6c61e04ba81def50c"), "msg2" : "Què? Com va la cosa?" }

Anem a fer ara una modificació del camp _id. A tots els efectes serà un document nou, ja que la manera d'identificar un document és per aquest camp:

> doc1._id=100
100

> doc1
{
    "_id" : 100,
    "msg" : "Hola, què tal?",
    "titol" : "Missatge 1",
    "destinatari" : "Ferran"
}

I ara anem a fer el save() d'aquest document:

> db.exemple.save(doc1)
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 100 })

Observeu com ara avisa que no n'ha trobat cap igual, i el que fa és inserir-lo (ens diu nUpserted, que és una barreja de Updated i Inserted; més avant tornarem a aquesta paraula)

> db.exemple.find()
{ "_id" : ObjectId("56ce310bc61e04ba81def50b"), "msg" : "Hola, què tal?", "titol" : "Missatge 1", "destinatari" : "Ferran" }
{ "_id" : ObjectId("56ce31f6c61e04ba81def50c"), "msg2" : "Què? Com va la cosa?" }
{ "_id" : 100, "msg" : "Hola, què tal?", "titol" : "Missatge 1", "destinatari" : "Ferran" }

Efectivament s'ha guardat com un nou document