Mongoose : performances et production
Définis dans le schéma :
schemaClient.index({ email: 1 }, { unique: true });schemaCommande.index({ client: 1, passeeLe: -1 });schemaCommande.index( { statut: 1 }, { partialFilterExpression: { statut: { $ne: 'expediee' } } },);schemaArticle.index({ nom: 'text', description: 'text' });schemaSession.index({ creeLe: 1 }, { expireAfterSeconds: 3600 }); // suppression automatique| Type d’index | Usage |
|---|---|
| Simple, composé | Filtres et tris (l’ordre des champs compte) |
unique |
Interdit les doublons |
partialFilterExpression |
Index limité à certains documents |
text |
Recherche textuelle |
expireAfterSeconds |
Suppression automatique (TTL) |
autoIndex en production
Section intitulée « autoIndex en production »Mongoose crée les index au démarrage (autoIndex: true par défaut). Sur une grosse collection, c’est coûteux et peut ralentir le démarrage : désactiver en production et gérer les index par une étape de déploiement.
await mongoose.connect(process.env.MONGODB_URI, { autoIndex: process.env.NODE_ENV !== 'production',});Script de synchronisation (à lancer lors d’un déploiement) :
import mongoose from 'mongoose';import './models/index.js';
await mongoose.connect(process.env.MONGODB_URI);await Promise.all(Object.values(mongoose.models).map((m) => m.syncIndexes()));await mongoose.disconnect();Vérifier l’usage d’un index
Section intitulée « Vérifier l’usage d’un index »const plan = await Commande.find({ client: id }) .sort({ passeeLe: -1 }) .explain('executionStats');console.log( plan.executionStats.totalDocsExamined, plan.executionStats.nReturned,);totalDocsExamined très supérieur à nReturned indique un index manquant. Plus de détails : MongoDB : index et performances.
Lectures efficaces
Section intitulée « Lectures efficaces »| Pratique | Effet |
|---|---|
.lean() |
Évite la création de documents Mongoose |
.select('champ1 champ2') |
Ne lit que les champs utiles |
.limit() systématique sur les listes |
Évite de charger toute la collection |
Curseur (.cursor()) pour les gros traitements |
Mémoire constante |
countDocuments avec filtre indexé, ou estimatedDocumentCount |
Évite un comptage lent |
Éviter les populate en boucle |
Une requête par appel : regrouper |
bulkWrite pour de nombreuses écritures |
Moins d’allers-retours |
await Client.bulkWrite([ { updateOne: { filter: { _id: id1 }, update: { $set: { actif: false } } } }, { insertOne: { document: { nom: 'Eve', email: 'eve@exemple.com' } } }, { deleteOne: { filter: { _id: id2 } } },]);Pool de connexions
Section intitulée « Pool de connexions »await mongoose.connect(process.env.MONGODB_URI, { maxPoolSize: 20, minPoolSize: 2, serverSelectionTimeoutMS: 5000, socketTimeoutMS: 45000,});Dimensionner maxPoolSize en fonction du nombre d’instances de l’application (chaque processus a son propre pool) et de net.maxIncomingConnections du serveur MongoDB. Avec le mode cluster de PM2 (voir PM2 : mode cluster), le nombre de connexions se multiplie par le nombre d’instances.
Requêtes lentes côté serveur
Section intitulée « Requêtes lentes côté serveur »Dans mongosh :
db.setProfilingLevel(1, { slowms: 100 });db.system.profile.find().sort({ ts: -1 }).limit(5).pretty();Voir MongoDB : index et performances. Activer le mode debug de Mongoose pour afficher les requêtes (développement seulement) :
mongoose.set('debug', process.env.NODE_ENV !== 'production');Sécurité
Section intitulée « Sécurité »- Compte MongoDB dédié à l’application, avec le rôle
readWritesur sa seule base (voir MongoDB : utilisateurs et droits). - Chaîne de connexion dans l’environnement ; mot de passe encodé.
- MongoDB n’écoute que sur
127.0.0.1ou le réseau privé ; pare-feu limité aux adresses des applications (voir UFW : écrire des règles). mongoose.set('sanitizeFilter', true)et validation des entrées contre l’injection NoSQL.- Ne pas renvoyer de champs sensibles (
select: false,toJSON). - Chiffrer les connexions (TLS) quand la base est sur un autre serveur :
?tls=true.
Service systemd
Section intitulée « Service systemd »/etc/monapi.env (droits 640) :
NODE_ENV=productionPORT=3000MONGODB_URI=mongodb://app:<mot-de-passe>@127.0.0.1:27017/boutique?authSource=boutique/etc/systemd/system/monapi.service :
[Unit]Description=API monapi (Express et Mongoose)After=network.target mongod.serviceWants=mongod.service
[Service]User=monapiGroup=monapiWorkingDirectory=/srv/monapi/appEnvironmentFile=/etc/monapi.envExecStart=/usr/bin/node src/serveur.jsRestart=on-failureRestartSec=3NoNewPrivileges=truePrivateTmp=trueProtectSystem=strictProtectHome=true
[Install]WantedBy=multi-user.targetsudo systemctl daemon-reloadsudo systemctl enable --now monapisudo journalctl -u monapi -fVoir Express : sécurité et production et systemd : écrire un service. L’application doit se reconnecter après un redémarrage de MongoDB : Mongoose le fait automatiquement.
Sauvegarde
Section intitulée « Sauvegarde »Les données se sauvegardent côté MongoDB (voir MongoDB : sauvegarde et restauration), pas par Mongoose.
Dépannage
Section intitulée « Dépannage »| Symptôme | Piste |
|---|---|
| Démarrage lent sur grosse base | autoIndex actif : le désactiver en production |
E11000 sur un champ unique après ajout de l’index |
Doublons existants : les nettoyer avant de créer l’index |
MongoServerSelectionError après une coupure |
MongoDB injoignable : systemctl status mongod, réseau, pare-feu |
MongoPoolClearedError / connection pool cleared |
Coupure réseau : vérifier la stabilité, ajuster serverSelectionTimeoutMS |
| Trop de connexions côté MongoDB | Plusieurs instances × maxPoolSize : réduire le pool |
| Mémoire qui croît | Lectures sans lean() sur de grosses listes, curseur non consommé, documents conservés en cache |
| Lenteur d’une requête | explain('executionStats') : index manquant |
Ubuntu 24.04 et 26.04 : différences à connaître
Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »Aucune propre à Ubuntu. La compatibilité dépend des versions de Mongoose, du pilote MongoDB intégré et du serveur MongoDB installé ; le chemin de node dépend de l’installation (which node).
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Index Mongoose, Connexions
- Suite : Dépannage