Durant sis mòduls, Escena Viva ha viscut d'un fitxer: dades/esdeveniments.json. Ens ha servit bé. Ens va ensenyar fs.promises, ens va permetre construir un domini ric amb Esdeveniment i Sessio, ens va donar de menjar per al servidor node:http del mòdul 4 i per a l'API Express del mòdul 6. Però en tancar aquell mòdul vam deixar una promesa pendent: el problema de l'aforament i la sobrevenda no es resolia amb validació ni amb errors ben tipats, perquè no és un problema de forma ni d'estat, sinó de concurrència i persistència. Aquest problema és la porta d'entrada d'aquest mòdul.

Aquí encara no escriurem ni un esquema de Mongoose ni una sentència CREATE TABLE. Farem una cosa més important: entendre què ens falta, què ens dóna un sistema gestor de bases de dades a canvi de què, com es tria entre el món relacional i el documental sense caure en bàndols, i com es dissenya el model de dades d'Escena Viva. Al final tindràs el plànol complet del que construirem en les cinc lliçons següents.

Contingut

  1. Per què un fitxer JSON deixa de servir
  2. Què aporta realment un SGBD
  3. Relacional davant de documental
  4. ACID, BASE i el teorema CAP aplicats a un aforament
  5. El panorama de bases de dades per a Node.js
  6. Controlador natiu davant d'ORM/ODM
  7. Dissenyar el model de dades d'Escena Viva
  8. El model definitiu en un diagrama
  9. Aïllar la persistència: el patró repositori
  10. Instal·lar MongoDB i comprovar la connexió

Per què un fitxer JSON deixa de servir

Siguem honestos i concrets. src/cataleg-dades.js no és un mal mòdul: llegeix dades/esdeveniments.json amb fs.promises, memoritza el resultat i exposa obtenirCataleg() i obtenirEsdevenimentPerId(). El problema no és el seu codi, és el seu model d'emmagatzematge. Aquestes són les fallades reals, no teòriques, que Escena Viva ja té avui:

  • Escriptures concurrents que es trepitgen. Si dues peticions venen entrades alhora, totes dues llegeixen el fitxer, totes dues modifiquen la seva còpia en memòria i totes dues el reescriuen sencer. L'última escriptura guanya i la primera venda desapareix. No hi ha blocatge, no hi ha arbitratge, no hi ha ningú que decideixi l'ordre. És exactament l'escenari de sobrevenda.
  • Escriptures no atòmiques. Un writeFile d'un catàleg complet es pot interrompre (fallada de disc, SIGKILL, contenidor reiniciat) i deixar un JSON truncat. Un JSON truncat no és un catàleg amb un esdeveniment menys: és un fitxer que ja no s'analitza, i l'aplicació no arrenca.
  • Tot el catàleg en memòria. Amb 3 esdeveniments i 7 sessions és gratis. Amb 40.000 esdeveniments històrics, cada procés Node carrega megabytes que mai no consulta. La memòria d'un procés és un recurs car i compartit amb el bucle d'esdeveniments.
  • Sense consultes eficients. "Dóna'm les sessions del Teatro Almendra entre l'1 i el 15 de març amb entrades lliures" avui es resol recorrent l'array sencer en JavaScript. És O(n) sobre tot el conjunt de dades, al fil principal, i no hi ha manera de millorar-ho sense escriure tu mateix un índex.
  • Sense integritat. Res no impedeix que una comanda apunti a ses-999-9, una sessió que no existeix. Res no impedeix que venudes superi l'aforament. Les invariants viuen només a les classes del domini, i si algú escriu el JSON a mà o un script se salta el domini, queden dades corruptes per sempre.
  • Sense historial. El fitxer només té l'estat actual. Quantes entrades es van vendre dimarts passat? Qui va anul·lar la comanda? No hi ha resposta: l'estat anterior es va sobreescriure.
  • Sense accés des de diversos processos. Aquest és el que més fa mal de cara al futur. Al mòdul 10 veurem cluster i arrencarem diversos processos Node per aprofitar tots els nuclis de la màquina. Amb un fitxer JSON, cada procés tindria la seva pròpia memòria cau i la seva pròpia idea de l'aforament; ni tan sols s'assabentarien de les vendes dels altres. La persistència en fitxer impedeix escalar. I al mòdul 11, en desplegar amb PM2 o diverses rèpliques en contenidors, el problema es multiplica pel nombre d'instàncies.

La conclusió no és que els fitxers siguin dolents. Un fitxer JSON és perfecte per a configuració, per a llavors, per exportar un informe. És dolent com a magatzem d'estat mutable compartit i concurrent. I això és precisament el que és l'aforament d'una sessió.

Què aporta realment un SGBD

Un sistema gestor de bases de dades (SGBD) és un procés especialitzat, normalment en una altra màquina o en un altre contenidor, la única feina del qual és custodiar dades. A canvi d'aprendre'l i d'operar-lo, et dóna sis coses que tu no reimplementaràs bé:

Garantia Què significa Què resol a Escena Viva
Persistència duradora Una escriptura confirmada sobreviu a una tallada de llum, gràcies al registre d'escriptura anticipada (WAL/journal) Mai no es perd una venda ja cobrada
Concurrència controlada Blocatges i control de versions perquè N clients escriguin alhora sense corrompre res Dos compradors simultanis no es trepitgen
Llenguatge de consulta Filtrar, ordenar, agrupar i agregar al motor, no al teu procés Informes de recaptació sense llegir tot el catàleg
Índexs Estructures auxiliars que converteixen cerques O(n) en O(log n) Cercar per sala o per rang de dates és instantani
Integritat Restriccions que el motor fa complir passi el que passi venudes <= aforament com a llei física, no com a bona intenció
Transaccions Diverses operacions que passen totes o cap Reservar aforament + crear comanda + emetre entrades com un sol acte

Fixa't en la darrera fila. És la que resol el problema que arrosseguem, i li dedicarem mitja lliçó 07-06.

Relacional davant de documental

Hi ha dues grans famílies que un desenvolupador de Node es troba cada dia. Cap no és "moderna" i l'altra "antiga"; cap no és "seriosa" i l'altra "de joguina". Són models amb compromisos diferents.

Criteri Relacional (PostgreSQL, MySQL) Documental (MongoDB)
Unitat de dades Fila en una taula, amb columnes fixes Document BSON, semblant a un objecte JSON imbricat
Esquema Rígid i declarat; canviar-lo requereix migració Flexible; el motor no exigeix forma, l'imposa el teu ODM
Relacions Claus foranes i JOIN resolts pel motor Referències resoltes amb consultes extra, o dades incrustades
Integritat referencial Sí, garantida pel motor No entre col·leccions; la garanteixes tu
Transaccions Natives, multitaula, des de sempre Atòmiques per document; multidocument des de la 4.0 amb rèpliques
Consultes complexes SQL, molt expressiu i optimitzat durant dècades Framework d'agregació, potent però diferent
Escalat Vertical i rèpliques de lectura; particionat més costós Particionat horitzontal (sharding) de sèrie
Casos ideals Dades molt relacionades, informes, diners, invariants dures Documents autocontinguts, esquema canviant, alt volum de lectura

La manera sana de llegir aquesta taula: tria el model que s'assembli al teu patró d'accés. Si la teva aplicació gairebé sempre llegeix "un esdeveniment amb totes les seves sessions", el documental et dóna això en una sola lectura de disc. Si la teva aplicació gairebé sempre creua cinc entitats per treure un informe, el relacional t'ho dóna en una sola consulta optimitzada.

Escena Viva, curiosament, té les dues cares: el catàleg és documental per naturalesa (un esdeveniment conté les seves sessions) i la venda és relacional per naturalesa (comandes, entrades, usuaris i diners). Per això aquest mòdul fa les dues coses: MongoDB serà la persistència oficial a les lliçons 2 a 4, i a les lliçons 5 i 6 modelarem el mateix a PostgreSQL per veure què canvia — i descobrirem que la sobrevenda es resol de manera especialment elegant allà.

ACID, BASE i el teorema CAP aplicats a un aforament

ACID descriu les garanties d'una transacció. Atomicitat: la transacció passa sencera o no passa. Consistència: en acabar, totes les regles de l'esquema continuen complint-se. Aïllament: dues transaccions simultànies no es veuen a mitges, el resultat és com si s'haguessin executat en algun ordre. Durabilitat: un cop confirmada, sobreviu a la fallada del servidor. Els sistemes relacionals van néixer amb ACID i els documentals l'han anat incorporant. BASE és el compromís contrari, típic de sistemes distribuïts massius: Basically Available (sempre respon), Soft state (l'estat pot estar en trànsit), Eventually consistent (si deixes d'escriure, en algun moment totes les rèpliques coincidiran). BASE canvia correcció immediata per disponibilitat i escala.

El teorema CAP explica per què existeix aquest canvi. En un sistema distribuït en què la xarxa es pot partir (i sempre pot), no es poden mantenir alhora consistència forta (C) i disponibilitat total (A): quan dos nodes deixen de veure's, o bé rebutges escriptures per no divergir, o bé les acceptes i divergiràs. Com que la tolerància a particions (P) no és opcional en una xarxa real, la decisió pràctica és entre CP (rebutjo escriptures dubtoses, continuo sent correcte) i AP (accepto tot, ja reconciliaré).

ACID BASE
Prioritza Correcció immediata Disponibilitat i escala
Davant d'una partició de xarxa Rebutja escriptures dubtoses (CP) Les accepta i reconcilia després (AP)
Estat després d'escriure Definitiu i visible per a tothom Pot trigar a propagar-se
Exemple a Escena Viva venudes d'una sessió, estat de la comanda Comptador de visites, recomanacions

Aplicat a Escena Viva: un aforament exigeix garanties fortes. Vendre una entrada de més no és un detall cosmètic que s'arregli "eventualment"; és una persona amb un codi EV-2026-000431 dreta a la porta del Teatro Almendra sense butaca, i un reemborsament, i una reclamació. El comptador venudes és l'exemple de llibre de dada que necessita consistència immediata: preferim rebutjar una compra dubtosa (CP) a acceptar-la i descobrir després que no hi havia lloc. En canvi, altres dades de la mateixa plataforma toleren perfectament consistència eventual: el nombre de visites de la pàgina d'un esdeveniment, les recomanacions, o la memòria cau del catàleg que veurem amb Redis al mòdul 10. La garantia es tria per dada, no per aplicació.

El panorama de bases de dades per a Node.js

Motor Família Punt fort Quan triar-lo Paquet npm
PostgreSQL Relacional El més complet: JSONB, tipus rics, transaccions sòlides, extensions Per defecte si dubtes i hi ha diners o invariants pel mig pg
MySQL / MariaDB Relacional Desplegament enorme, operació coneguda, molt ràpid en lectures simples Ecosistema o allotjament que ja l'imposa mysql2
SQLite Relacional incrustada Sense servidor: la base de dades és un fitxer Aplicacions d'escriptori, CLI, proves, prototips better-sqlite3
MongoDB Documental Documents imbricats, esquema flexible, sharding de sèrie Dades autocontingudes i amb forma canviant mongodb
Redis Clau-valor en memòria Latència de microsegons, estructures de dades, TTL Memòria cau, sessions, cues — és del mòdul 10, no un magatzem principal redis

Redis mereix un aclariment perquè es malinterpreta molt: no és "una base de dades més ràpida", és una base de dades en memòria amb un model de durabilitat diferent. S'utilitza davant de la base de dades principal, no en el seu lloc. Al mòdul 10 la farem servir per posar el catàleg a la memòria cau i per encuar els correus de confirmació.

Controlador natiu davant d'ORM/ODM

Entre el teu codi i el motor sempre hi ha un controlador (driver): parla el protocol binari de la base de dades i exposa una API de baix nivell. A sobre hi pot haver un ORM (Object-Relational Mapper, món SQL) o un ODM (Object-Document Mapper, món documental), que tradueix entre files o documents i objectes de JavaScript.

Aspecte Controlador natiu ORM / ODM
Control sobre la consulta Total, escrius exactament el que s'executa Indirecte: la genera la biblioteca
Rendiment màxim El sostre del motor Una mica menys, per la capa de traducció
Esquema i validació L'escrius tu Declarativa, inclosa
Relacions Les resols a mà populate / include
Migracions Teves Eina integrada
Corba d'aprenentatge Aprens el motor Aprens el motor i la biblioteca
Risc Codi repetitiu, errors manuals Consultes ineficients que no veus, "màgia" difícil de depurar

El que et dóna un ORM/ODM: menys codi repetitiu, validació declarativa, tipus coherents, hooks, migracions i un model mental uniforme per a tot l'equip. El que et treu: transparència. Una línia innocent pot generar 200 consultes (el problema N+1 que veurem a la lliçó 07-04). La regla professional és: fes servir l'ORM per al 95 % del codi i no tinguis por de baixar a consultes en cru per al 5 % que importa, mesurant abans de decidir. En aquest mòdul farem servir Mongoose (ODM) i Sequelize (ORM), i en tots dos casos veurem com escapar a la consulta crua.

Dissenyar el model de dades d'Escena Viva

Abans d'escriure un esquema cal decidir què és una entitat. Una entitat és quelcom que té identitat pròpia i cicle de vida propi: existeix abans i després de l'operació que la va crear, i té sentit cercar-la per si mateixa. Un esdeveniment és una entitat. Una comanda és una entitat. El nom de la sala, en canvi, és un atribut.

La segona decisió és què s'agrupa i què se separa. Al món documental això s'anomena incrustar davant de referenciar i ho estudiarem a fons a la lliçó 07-04, però el criteri ja el podem aplicar amb dues preguntes:

  1. Es llegeixen sempre junts? Si mai no demanes una sessió sense el seu esdeveniment, agrupa'ls.
  2. Creix sense límit? Si la col·lecció filla creix indefinidament, separa-la.

Apliquem-ho a les nostres entitats:

  • Esdeveniment amb les seves sessions incrustades. Un esdeveniment té entre 1 i 7 sessions al nostre catàleg; una obra en cartell en podria tenir 60. És un nombre acotat i conegut per endavant. A més, la pantalla de detall de l'esdeveniment i la mateixa API (GET /esdeveniments/:id) les demanen sempre juntes: ja avui el controlador llistarSessionsDeLEsdeveniment parteix d'un Esdeveniment carregat. I la seva mida és minúscula. S'incrusten.
  • Comanda com a col·lecció a part. Les comandes creixen sense sostre: un esdeveniment popular en pot acumular desenes de milers. Tenen cicle de vida propi (pendent → pagat → emes | anullat) i es consulten pel seu compte ("les meves comandes"). Ficar-les dins de l'esdeveniment faria créixer el document fins a rebentar el límit i obligaria a reescriure'l sencer a cada compra. Se separen.
  • Entrada com a col·lecció a part. Cada entrada té el seu codi únic EV-2026-000431, el seu estat (valida → usada | anullada) i es valida individualment a la porta, escanejant. És la unitat d'accés més petita del sistema i la de més volum. Se separa, amb referències a la comanda i a la sessió.
  • Usuari com a col·lecció a part, amb el seu rol (assistent, organitzador, administrador). En aquest mòdul el creem sense contrasenyes ni autenticació: això és íntegrament el mòdul 8. Aquí només deixem el forat preparat.

I una tercera decisió, deliberadament incòmoda: el comptador venudes viu dins de la sessió, encara que es podria calcular comptant entrades vàlides. És una desnormalització a propòsit, perquè comprovar l'aforament sigui una lectura d'un camp i no una agregació. El preu és mantenir la coherència entre el comptador i les entrades reals; aquest preu el paguem amb les tècniques de la lliçó 07-06.

El model definitiu en un diagrama

erDiagram
    USUARI ||--o{ COMANDA : "realitza"
    ESDEVENIMENT ||--|{ SESSIO : "conte (incrustada)"
    COMANDA ||--|{ ENTRADA : "agrupa"
    SESSIO ||--o{ ENTRADA : "es reservada per"

    USUARI {
        string _id
        string correu
        string nom
        string rol
    }
    ESDEVENIMENT {
        string _id
        string esdevenimentId
        string titol
        string sala
        string organitzadorId
        string categoria
        string estat
        int duracioMinuts
    }
    SESSIO {
        string sessioId
        date dataHora
        int aforament
        int venudes
        int preuCentims
    }
    COMANDA {
        string _id
        string usuariId
        string sessioId
        int quantitat
        int totalCentims
        string estat
        string canal
    }
    ENTRADA {
        string _id
        string codi
        string comandaId
        string sessioId
        string estat
    }

Llegeix-ho així: SESSIO apareix com a entitat al diagrama perquè conceptualment ho és, però físicament viu dins del document ESDEVENIMENT com a subdocument. COMANDA i ENTRADA són col·leccions independents que es relacionen per referència. Aquest és el plànol que implementarem a la lliçó 07-02 amb Mongoose i que traduirem a taules a la 07-05 amb Sequelize — on SESSIO sí que serà una taula pròpia, i veurem per què.

Aïllar la persistència: el patró repositori

Aquí va l'advertència d'arquitectura més important del mòdul. Si els controladors criden directament Esdeveniment.find(...), la teva aplicació queda casada amb MongoDB per sempre. Canviar de motor, o provar amb dades falses, o consultar dues fonts diferents, exigiria reescriure tots els controladors.

La solució és una capa fina: src/repositoris/. Un repositori exposa operacions en el llenguatge del negoci (obtenirCataleg, obtenirEsdevenimentPerId, reservarAforament, crearComanda) i amaga per complet com es compleixen. Per damunt d'ell, controladors i domini no saben si a sota hi ha Mongo, Postgres o un array.

// src/repositoris/esdeveniments.js (contracte, la implementacio arriba a la llico 07-03)
'use strict';

/**
 * Retorna el cataleg complet com a instancies del domini.
 * Qui crida no sap si ve de Mongo, de Postgres o d'un fitxer.
 */
async function obtenirCataleg() {
  throw new Error('sense implementar');
}

/** Retorna un Esdeveniment del domini, o null si no existeix. */
async function obtenirEsdevenimentPerId(esdevenimentId) {
  throw new Error('sense implementar');
}

module.exports = { obtenirCataleg, obtenirEsdevenimentPerId };

Fixa't en el detall decisiu: és exactament la signatura pública de src/cataleg-dades.js. Per això podrem substituir el mòdul sencer sense tocar src/controladors/esdeveniments.js. I per això, a la lliçó 07-05, escriurem una segona implementació sobre Sequelize sense canviar una línia de l'aplicació. El repositori retorna objectes del domini (Esdeveniment, Sessio), no documents de Mongoose: així el domini conserva els seus getters (ocupacio, exhaurida) i les seves invariants, tal com els vam deixar al mòdul 2.

Instal·lar MongoDB i comprovar la connexió

Tres camins, tots vàlids. Tria'n un.

Opció A: servei local. Instal·la MongoDB Community Server des del lloc oficial i arrenca'l com a servei del sistema:

# Comprovar que el servei esta viu (Linux amb systemd)
sudo systemctl status mongod
sudo systemctl start mongod

Opció B: Docker. La més neta perquè no embruta la teva màquina i s'esborra en una ordre. Al mòdul 11 formalitzarem això amb docker compose:

# Aixeca MongoDB 7 al port estandard, amb volum persistent
docker run -d --name mongo-escena-viva \
  -p 27017:27017 \
  -v escena-viva-dades:/data/db \
  mongo:7

Opció C: MongoDB Atlas. El servei gestionat al núvol. Té una capa gratuïta suficient per a aquest curs; et donarà una URL del tipus mongodb+srv://usuari:[email protected]/escena_viva. És el que faràs servir en producció si no vols operar el motor tu mateix.

Sigui quina sigui l'opció, comprova la connexió amb el client oficial mongosh:

# Connectar a la base de dades del curs
mongosh "mongodb://localhost:27017/escena_viva"

I dins de l'intèrpret:

// Veure en quina base som (la crea al primer escrit, no abans)
db.getName();               // 'escena_viva'

// Inserir un document de prova i recuperar-lo
db.prova.insertOne({ sala: 'Teatro Almendra', creat: new Date() });
db.prova.find();

// Netejar
db.prova.drop();

Una peculiaritat que sorprèn: MongoDB no crea la base de dades ni la col·lecció fins al primer document. Si show dbs no llista escena_viva acabat de connectar, no és un error.

L'URL de connexió no s'escriurà mai a mà al codi. Anirà a .env i es llegirà des de src/config/index.js, que ja és l'únic punt de l'aplicació que toca process.env:

# .env
MONGODB_URL=mongodb://localhost:27017/escena_viva

I amb la connexió comprovada, convé fixar per endavant quines preguntes farà l'aplicació, perquè el model de dades es dissenya des de les consultes cap enrere. Aquestes són les cinc consultes més freqüents d'Escena Viva, i són les que governaran els índexs de la lliçó 07-02:

Consulta Freqüència Entitat de partida
Catàleg d'esdeveniments publicats Molt alta Esdeveniment
Detall d'un esdeveniment amb les seves sessions Molt alta Esdeveniment
Comprovar l'aforament lliure d'una sessió Molt alta (crítica) Sessió dins de l'Esdeveniment
Comandes d'un usuari Mitjana Comanda
Validar una entrada pel seu codi a la porta Alta en horari de funció Entrada

Errors Comuns i Consells

  • Triar el motor per moda. "Fem servir Mongo perquè és JavaScript" no és un criteri. El criteri és el patró d'accés, les garanties que necessites i el que el teu equip sap operar.
  • Creure que "sense esquema" significa "sense disseny". MongoDB no t'obliga a declarar una forma, però les teves dades la tenen igualment. Si no la decideixes tu, la decidirà cada insert que escriguis, i acabaràs amb set variants del mateix document.
  • Ficar l'URL de connexió al codi. Amb credencials a dins i pujada a git. Va a la configuració, sempre. Ja tens el lloc: src/config/index.js.
  • Deixar la base de dades sense autenticació "perquè és desenvolupament". Un MongoDB exposat al 27017 sense usuari és dels blancs preferits dels escàners automàtics. En local, com a mínim no publiquis el port fora de localhost.
  • Consell: abans de modelar, escriu les cinc consultes que la teva aplicació farà més vegades. El model de dades es dissenya des de les consultes cap enrere, no des de les entitats cap endavant.
  • Consell: conserva dades/esdeveniments.json. No l'esborrarem: a la lliçó 07-06 es convertirà en la llavor que carrega la base de dades. Es jubila com a magatzem, no com a font.

Exercicis

Exercici 1: auditoria del teu propi codi

Obre src/cataleg-dades.js i src/controladors/comandes.js i localitza, sense executar res, els punts exactes on dues peticions simultànies poden corrompre l'estat. Escriu per a cadascun: quina línia llegeix, quina línia escriu, i què passa si una altra petició es cola entre totes dues.

Exercici 2: decidir el model

Escena Viva vol afegir dues coses: (a) les ressenyes que els assistents deixen sobre un esdeveniment, i (b) el plànol de butaques de cada sala. Per a cadascuna, decideix si s'incrusta o se separa i justifica la decisió amb els dos criteris d'aquesta lliçó (lectura conjunta i creixement).

Exercici 3: triar garanties

Classifica aquestes quatre dades segons necessitin consistència forta o eventual, i justifica-ho: (1) venudes d'una sessió, (2) el comptador de visites de la fitxa d'un esdeveniment, (3) l'estat d'una comanda, (4) el llistat d'"esdeveniments recomanats per a tu".

Solucions

Exercici 1. El patró perillós és sempre llegir-modificar-escriure sense exclusió mútua. Al flux de compra: es llegeix el catàleg memoritzat, es comprova sessio.lliures >= quantitat, es crida sessio.vendre() i es persisteix. Si dues peticions executen la comprovació abans que qualsevol de les dues escrigui, totes dues la superen encara que només quedi una entrada. La memorització empitjora les coses: la còpia en memòria pot portar minuts desactualitzada respecte al fitxer. I com que Node és monofil, el forat s'obre exactament a cada await — el bucle d'esdeveniments del mòdul 2 cedeix el torn just allà.

Exercici 2. (a) Les ressenyes se separen: creixen sense límit (un festival en pot acumular milers), no calen per renderitzar el catàleg, es paginen i s'ordenen per data, i es moderen amb cicle de vida propi. (b) El plànol de butaques s'incrusta a la sala (o es referencia com a catàleg a part si diverses sales comparteixen plantilla), perquè és de mida acotada, no canvia gairebé mai i sempre es llegeix juntament amb la sala. Compte: l'ocupació de cada butaca en una sessió concreta sí que és volàtil i de molta escriptura, així que aquest estat no ha de viure al plànol estàtic.

Exercici 3. (1) venudes: forta, és la definició mateixa del problema de sobrevenda. (3) Estat de la comanda: forta, decideix si es cobra i si s'emeten entrades; una lectura obsoleta pot duplicar un cobrament. (2) Visites: eventual, un error d'un 2 % durant uns segons no perjudica ningú i a canvi permet comptar en memòria i abocar per lots. (4) Recomanacions: eventual, es calculen en diferit i ningú no nota que porten una hora de retard.

Conclusió

Hem tancat l'etapa del fitxer. Ara saps, amb noms concrets, què li falta a dades/esdeveniments.json: atomicitat, concurrència, consultes, índexs, integritat, historial i accés multiprocés. Saps què et dóna un SGBD a canvi, què separa el model relacional del documental sense necessitat de prendre partit, i per què un aforament pertany al territori de les garanties fortes segons ACID i CAP. Has vist el panorama real de motors per a Node i el compromís entre baixar al controlador natiu o recolzar-te en un ORM/ODM. I, sobretot, tens el model de dades d'Escena Viva decidit i raonat: Esdeveniment amb les seves sessions incrustades, Comanda, Entrada i Usuari com a col·leccions separades, amb el comptador venudes desnormalitzat a propòsit.

També tens la peça d'arquitectura que sosté tot el mòdul: src/repositoris/, la frontera que impedirà que el motor de base de dades es filtri als controladors i al domini.

A la lliçó següent baixem al codi. Connectarem amb MongoDB des de src/config/index.js, escriurem src/db/connexio.js amb la seva obertura en arrencar i el seu tancament a l'aturada ordenada que ja existeix a src/servidor.js, i traduirem aquest diagrama a esquemes i models de Mongoose a src/models/: tipus, validadors, virtuals, middleware d'esquema i índexs. El plànol es converteix en estructura.

Curs de Node.js: De Principiant a Avançat

Mòdul 1: Introducció a Node.js

Mòdul 2: Conceptes Bàsics

Mòdul 3: Sistema de Fitxers i E/S

Mòdul 4: HTTP i Servidors Web

Mòdul 5: NPM i Gestió de Paquets

Mòdul 6: Framework Express.js

Mòdul 7: Bases de Dades i ORMs

Mòdul 8: Autenticació i Autorització

Mòdul 9: Proves i Depuració

Mòdul 10: Temes Avançats

Mòdul 11: Desplegament i DevOps

Mòdul 12: Projectes del Món Real

© Copyright 2026. Tots els drets reservats