Il tuo e-commerce sta crescendo e il database relazionale inizia a scricchiolare: query lente, JOIN mostruosi, schemi rigidi che non reggono la variabilità dei prodotti. Ti hanno parlato di NoSQL e MongoDB, ma non sai se è la soluzione giusta. Noi di Meteora Web lo usiamo da anni, e abbiamo visto sia successi che fallimenti. In questa guida pillar ti spieghiamo cos'è MongoDB, quando conviene, come progettare i documenti, ottimizzare le performance e gestirlo in produzione. Partiamo dal problema vero: il tuo database non deve essere un collo di bottiglia.
MongoDB vs SQL: Quando Usare NoSQL e Quando No
La domanda sbagliata è “qual è il database migliore?”. Quella giusta è “quale database risolve il mio problema con il miglior rapporto costo/performance?”. Veniamo dalla contabilità: bilanci, partita doppia, IVA. Per questo ragioniamo sui numeri del cliente, non solo sul design. Un database relazionale (PostgreSQL, MySQL) è perfetto per dati fortemente correlati, transazioni ACID classiche e report aggregati con JOIN prevedibili. MongoDB eccelle quando hai dati semi-strutturati, schema variabile, volumi elevati di scritture e letture semplici con modelli a documento.
I Segnali Che Indicano MongoDB
- I tuoi dati sono naturalmente gerarchici o annidati (es. un ordine con array di prodotti).
- Lo schema cambia spesso e non vuoi migrazioni continue.
- Devi scalare in orizzontale (sharding) senza il collo di bottiglia dei JOIN distribuiti.
- Le tue query sono prevalentemente per ID o attributi semplici, non JOIN complessi.
Esempio concreto: un cliente gestiva un catalogo di abbigliamento con varianti taglia/colore/prezzo. In SQL servivano 3 tabelle e JOIN. In MongoDB un singolo documento con array di varianti ha dimezzato la latenza delle query e semplificato il codice.
Sponsored Protocol
Document Model: Schema Design e Embedding vs Referencing
In MongoDB non esiste lo schema fisso, ma una cattiva progettazione dei documenti ti costerà cara in termini di performance e complessità. Bisogna scegliere tra embedding (annidare i dati correlati) e referencing (usare riferimenti come in SQL).
Embedding: Quando e Come
Incorpora i dati quando li leggi sempre insieme e le modifiche sono atomiche. Esempio: un post del blog con commenti (se il numero di commenti è limitato).
{
_id: ObjectId("post123"),
title: "MongoDB guida",
comments: [
{ user: "Mario", text: "Ottimo articolo" },
{ user: "Luigi", text: "Grazie!" }
]
}
Referencing: Quando Evitare l'Embedding
Se i dati embedded crescono illimitatamente o vengono aggiornati da contesti diversi, usa riferimenti e JOIN (con $lookup). Esempio: utenti e ordini.
// Ordine
{
_id: ObjectId("order001"),
userId: ObjectId("user789"),
items: ["prod001", "prod002"]
}
// Utente
{
_id: ObjectId("user789"),
name: "Mario"
}
Regola pratica: se la relazione è uno-a-molti con pochi elementi e lettura congiunta, embedda. Se è molti-a-molti o array potenzialmente enormi, reference.
CRUD MongoDB: Operazioni Base e Driver
MongoDB espone un'API nativa JSON-like. I driver ufficiali per Node.js e Python sono maturi e performanti. Ecco come eseguire le operazioni fondamentali con il driver Node.js.
Connessione e Inserimento
const { MongoClient } = require('mongodb');
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const db = client.db('ecommerce');
const products = db.collection('products');
await products.insertOne({ name: 'T-shirt', price: 29.99, stock: 100 });
Lettura, Aggiornamento e Cancellazione
// Lettura
const product = await products.findOne({ name: 'T-shirt' });
// Aggiornamento
await products.updateOne(
{ name: 'T-shirt' },
{ $inc: { stock: -1 } }
);
// Cancellazione
await products.deleteOne({ name: 'T-shirt' });
Attenzione: in produzione non usare find() senza filtro su collezioni grandi. Metti sempre un indice e limita i documenti restituiti con .limit().
Sponsored Protocol
Aggregation Pipeline: Group, Match, Lookup e Project
Il vero potenziale di MongoDB sta nell'aggregation pipeline. Unisce la potenza di SQL a una flessibilità maggiore. È una sequenza di stadi ($match, $group, $sort, $project, $lookup) che trasformano i documenti passo dopo passo.
Esempio: Vendite per Categoria con Lookup
db.orders.aggregate([
{ $match: { status: 'completed' } },
{ $unwind: '$items' },
{
$lookup: {
from: 'products',
localField: 'items.productId',
foreignField: '_id',
as: 'product'
}
},
{ $unwind: '$product' },
{
$group: {
_id: '$product.category',
totalSales: { $sum: '$items.price' },
count: { $sum: 1 }
}
},
{ $sort: { totalSales: -1 } },
{ $project: { category: '$_id', totalSales: 1, count: 1, _id: 0 } }
]);
Questo sostituisce 3 query SQL con una pipeline. La performance dipende dagli indici su status, productId e category.
Indici MongoDB: Compound, Text, Geospatial e Performance
Un database senza indici è una biblioteca senza catalogo. MongoDB supporta diversi tipi di indici per accelerare le query.
Indice Compound
db.products.createIndex({ category: 1, price: -1 });
Usalo per query che filtrano per categoria e ordinano per prezzo decrescente.
Indice Text per Ricerca Full-Text
db.products.createIndex({ name: 'text', description: 'text' });
db.products.find({ $text: { $search: 't-shirt cotone' } });
Non sostituisce un motore di ricerca specializzato (Elasticsearch), ma per cataloghi di dimensioni medio-piccole è sufficiente.
Sponsored Protocol
Indice Geospaziale
db.places.createIndex({ location: '2dsphere' });
db.places.find({
location: {
$near: {
$geometry: { type: 'Point', coordinates: [13.3615, 38.1157] },
$maxDistance: 5000
}
}
});
Consiglio operativo: usa explain('executionStats') per capire se la query sfrutta l'indice. Noi lo facciamo sempre prima di mettere in produzione.
Mongoose ODM: Schema Validation e Middleware
Mongoose è l'ODM più diffuso per Node.js. Fornisce uno schema lato applicazione, validazione, middleware (pre/post) e popolamento automatico delle reference. Non sostituisce la validazione lato database, ma la integra.
Definire uno Schema
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: { type: String, required: true, index: true },
price: { type: Number, min: 0 },
category: { type: String, enum: ['abbigliamento', 'accessori'] },
variants: [{
size: String,
color: String,
stock: Number
}]
}, { timestamps: true });
productSchema.pre('save', function(next) {
this.updatedAt = new Date();
next();
});
const Product = mongoose.model('Product', productSchema);
Middleware e Hooks
Usa i middleware per loggare le modifiche o invalidare cache. Esempio: dopo il salvataggio, invalida la cache Redis.
productSchema.post('save', function(doc) {
redisClient.del(`product:${doc._id}`);
});
MongoDB Atlas: Cloud Database Setup e Configurazione
MongoDB Atlas è il servizio cloud ufficiale. Gestisce replica set, backup, scaling e monitoraggio. Noi lo consigliamo per progetti in produzione, perché elimina la gestione dell'infrastruttura e offre un tier gratuito per test.
Sponsored Protocol
Setup Base
- Crea un cluster gratuito (M0) su atlas.mongodb.com
- Configura IP whitelist o Private Endpoint per la sicurezza
- Crea un utente database con credenziali forti
- Connetti tramite URI:
mongodb+srv://user:password@cluster0.xxxxx.mongodb.net/myDB?retryWrites=true&w=majority
Attenzione: non esporre mai le credenziali in codice. Usa variabili d'ambiente e gestori di segreti.
Transactions MongoDB: ACID e Multi-Document Operations
A partire dalla versione 4.0, MongoDB supporta transazioni ACID multi-document. Utili per operazioni che coinvolgono più documenti in collezioni diverse, ad esempio un trasferimento di fondi tra due conti.
Esempio di Transazione
const session = client.startSession();
session.startTransaction();
try {
await accounts.updateOne(
{ _id: fromId },
{ $inc: { balance: -amount } },
{ session }
);
await accounts.updateOne(
{ _id: toId },
{ $inc: { balance: amount } },
{ session }
);
await session.commitTransaction();
} catch (error) {
await session.abortTransaction();
throw error;
} finally {
session.endSession();
}
Performance: le transazioni in MongoDB hanno un costo maggiore rispetto a un'operazione atomica singola. Usale solo quando strettamente necessario. Per la maggior parte dei casi, le operazioni atomiche su un singolo documento sono sufficienti.
Change Streams: Notifiche Real-Time sui Dati
MongoDB Change Streams permette di ascoltare in tempo reale le modifiche a una collezione, database o intero cluster. Utile per reagire a insert, update, delete senza polling.
Esempio con Node.js
const changeStream = db.collection('orders').watch();
changeStream.on('change', (change) => {
console.log('Nuovo ordine:', change.fullDocument);
// Invia notifica, aggiorna cache, ecc.
});
Integrazione perfetta con websocket o serverless per applicazioni real-time come dashboard di monitoraggio.
Sponsored Protocol
Performance Tuning: Explain e Query Optimization
La maggior parte dei problemi di performance in MongoDB deriva da indici mancanti o mal progettati, documenti troppo grandi (più di 16 MB) e query senza filtri. Noi utilizziamo explain() in tutte le fasi di sviluppo.
Usare explain per Diagnosticare
db.products.find({ category: 'abbigliamento' }).sort({ price: -1 }).explain('executionStats');
Cerca: winningPlan che mostri IXSCAN (index scan) invece di COLLSCAN. Se vedi COLLSCAN significa che la query non usa alcun indice. Aggiungilo subito.
Principali KPI da Monitorare
- Query Execution Time: >100ms per query frequente è un campanello d'allarme.
- Documenti restituiti vs esaminati: un rapporto basso indica un indice poco selettivo.
- Dimensione del working set: deve entrare in RAM per evitare page fault su disco.
In Sintesi — Cosa Fare Adesso
Non scegliere MongoDB perché è di moda. Valuta il tuo caso d'uso. Se hai dati relazionali complessi, resta su PostgreSQL. Se hai documenti JSON con schema variabile e devi scalare, MongoDB è la scelta giusta.
- Analizza i tuoi dati: schema attuale, volumi, pattern di accesso.
- Progetta i documenti seguendo la regola dell'embedding vs referencing.
- Definisci indici su ogni campo usato in query filtro o ordinamento.
- Testa con dati reali usando
explain()e metriche di performance. - Scegli Atlas se non vuoi gestire l'infrastruttura, ma tieni d'occhio i costi.
Noi di Meteora Web usiamo MongoDB in produzione per applicazioni real-time, e-commerce e piattaforme dati. Se vuoi approfondire, contattaci. La tecnologia si sceglie in base ai numeri, non alle mode.