<div class="page"> <div class="cover text-center"> <img class="mx-auto" src=/itb/images/logo_mislata.png alt="logo"> # Relacions i documents anidats <div class="text-end fit-content ms-auto my-3 mt-auto pt-3"> <p><strong>Autor:</strong> Joan Puigcerver Ibáñez</p> <p><strong>Correu electrònic:</strong> j.puigcerveribanez@edu.gva.es</p> <p><strong>Curs:</strong> 2023/2024</p> </div> <div> <p class="fw-bold mb-0">Llicència: BY-NC-SA</p> <p class="d-none d-md-block">(Reconeixement - No Comercial - Compartir Igual)</p> <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.ca" target="_blank"> <img class="mx-auto" src="/itb/images/license.png" alt="Licence"/> </a> </div><!--license--> </div><!--cover--> </div><!--page--> {:toc} ## Introducció Les bases de dades relacionals basen la seua estructura en taules i les relacions entre cada una d'elles. Aquesta estructura és molt útil per a molts casos, sobretot quan totes les dades d'una tenen una estructura idèntica. En canvi, quan les dades són més complexes podem decidir utilitzar un altre tipus de bases de dades, com __MongoDB__. Aquesta base de dades és una base de dades NoSQL, que permet emmagatzemar documents en format JSON. L'estructura de __claus-valor__ que ens proporciona MongoDB és molt flexible i ens ofereix diferents possibilitats per modelar les dades i les relacions entre elles. Quant a les relacions, en MongoDB es poden modelar de dues maneres: - **Referències entre documents**: Simulant el comportament de les claus foranes de les bases de dades relacionals, un camp del document fa referència a un identificador d'un altre document. - **Documents anidats**: Un document (_objecte_) pot contindre un altre document (_objecte_) com a camp, amb tota la informació de l'onjecte anidat. Segons la cardinalitat, generalment les relacions es modelen de la següent manera: - **1 a 1**: S'utilitza un document anidat. - **1 a N**: - Si el nombre de documents relacionats és xicotet, es poden utilitzar documents anidats. - Si el nombre de documents relacionats és gran, es recomana utilitzar referències entre documents. - **N a N**: S'utilitza un array de referències a documents. ::: docs - Documentació oficial de MongoDB sobre relacions entre documents: https://www.mongodb.com/docs/manual/applications/data-models-relationships/ ::: ## Documents anidats Els __documents anidats__ són objectes que es troben dins d'altres objectes. Quan un valor d'un camp conté dades complexes, es pot crear un nou objecte amb dades estructurades __clau-valor__. ::: docs Documentació oficial de MongoDB sobre documents anidats: https://www.mongodb.com/resources/products/fundamentals/embedded-mongodb ::: ```mongodb database> db.collection.insertOne({ field1: "value1", field2: { field3: "value3", field4: "value4", } }) ``` ::: example En aquest exemple hem creat un nou `autor`, que conté una llista de `llibres` que ha escrit. Cada `llibre` és un objecte anidat dins de l'objecte `autor`. ```mongodb llibres> db.autors.insertOne({ _id: 0, nom: "Irene Solà", data_naixement: new Date("1990-09-16"), nacionalitat: "Espanyola", biografia: "Irene Solà (Malla, 1990) és escriptora i traductora...", llibres: [ { _id: 0, isbn: "9788433915689", titol: "Canto jo i la muntanya balla", resum: "Canto jo i la muntanya balla és una novel·la...", nombre_pagines: 162, data_publicacio: new Date("2019-06-07"), } ] }) ``` ::: ## Relacions entre documents Tots els documents de MongoDB tenen un __identificador únic__ que s'emmagatzema en el camp `_id`, que actua com a clau primària. Aquest identificador pot ser de qualsevol tipus i pot ser especificat en el moment de la creació del document. Si no s'especifica, MongoDB crea un identificador de tipus `ObjectId`. Per a modelar relacions entre documents, podem utilitzar aquest identificador com a __clau forana__. ```mongodb database> db.collection1.insertOne({ _id: 0, field1: "value1", }) database> db.collection2.insertOne({ _id: 0, collection1_id: 0 }) ``` :::: info També podem utilitzar un altre camp com a __clau forana__. En aquest cas, es recomana crear un __índex__ en aquest camp per optimitzar les consultes que utilitzen aquest camp per realitzar la búsqueda. ::: docs MongoDB índexs: https://www.mongodb.com/docs/manual/indexes/ ::: :::: ::: example En aquest exemple hem creat un document a la col·lecció `reviews` que referencia a un llibre, document anidat a la col·lecció `autors`. ```mongodb llibres> db.reviews.insertOne({ _id: 0, autor_id: 0, llibre_id: 0, puntuacio: 5, comentari: "M'ha encantat aquest llibre, és una obra mestra!" }) ``` ::: ## Avantatges i desavantatges Cada manera de modelar les relacions té els seus avantatges i desavantatges. Els __documents anidats__ són molt útils quan les dades relacionades són xicotetes o quan el nombdre de documents adinats és xicotet. També són molt útils en relacions 1 a 1, ja que tota la informació es troba en un sol document i no cal relacionar altres documents. No obstant això, si el nombre de documents anidats és gran, pot ser complicat realitzar emmagatzemar-los tots en un mateix document, ja que cada document té un límit de 16MB i si s'excedeix aquest límit, serà necessari dividir les dades en més documents. En canvi, les __referències entre documents__ són molt útils quan el nombre de documents relacionats és gran, ja que permeten dividir les dades en diferents documents i relacionar-los entre ells. A més, redueix la redundància de dades, ja que no cal emmagatzemar la mateixa informació en diferents documents. No obstant això, les referències entre documents poden ser més lentes que els documents anidats, ja que requereixen realitzar més consultes per obtenir tota la informació relacionada. ## Bibliografia - https://www.mongodb.com/resources/products/fundamentals/embedded-mongodb - https://www.mongodb.com/docs/manual/indexes/ - https://www.mongodb.com/docs/manual/applications/data-models-relationships/