En construisant Ekit, un outil SaaS collaboratif reposant sur des schémas hautement dynamiques, nous nous sommes heurtés à une problématique MongoDB fréquente dans les plateformes orientées développeurs.
Lorsque les utilisateurs peuvent définir librement leurs champs personnalisés, créer un nouvel index à chaque évolution du schéma n’est tout simplement pas viable.
Cet article présente une approche éprouvée en production, validée sur un dataset d’environ 15 millions de documents.
Le défi
La difficulté principale réside dans la capacité à autoriser des champs définis dynamiquement par les utilisateurs tout en conservant des performances prévisibles.
Sur de petites collections, les index wildcard peuvent donner de bons résultats, mais leur comportement devient beaucoup moins fiable à grande échelle.
La mise en place
Afin de garantir une indexation stable et maîtrisée, j’ai mis en œuvre une approche basée sur l’index slotting.
Les champs personnalisés sont mappés vers un ensemble restreint et fixe de slots indexés.
Pour valider cette architecture, environ 15 millions de documents ont été injectés dans la collection.
Au départ, nous pensions que les performances dépendraient principalement des index. En pratique, la forme des requêtes et la stratégie de pagination se sont révélées tout aussi déterminantes.
- 4 slots de type chaîne de caractères
- 1 slot de type entier
- 1 slot de type date
Ce qui a eu le plus d’impact
Recherche par préfixe ancré
En structurant les requêtes autour de recherches par préfixe ancré, certains accès sont passés de plusieurs secondes à environ 2–3 millisecondes.
L’analyse avec explain() a montré très clairement pourquoi : une fois l’index correctement exploité, le nombre de documents parcourus chute drastiquement.
Pagination par keyset plutôt que par offset
La pagination basée sur skip() et limit() ne passe pas à l’échelle avec un tel volume de données.
Le passage à une pagination par keyset permet à chaque requête de parcourir une plage réduite et prévisible.
La latence reste ainsi stable autour de 2 millisecondes, même lors de navigations profondes dans le dataset.
Résultat
Une fois ces ajustements en place, le système s’est stabilisé très rapidement.
Ce n’est pas une solution universelle, mais il a été rassurant de constater que MongoDB pouvait gérer cette charge proprement, pendant que nous continuions à travailler sur l’UX collaborative d’Ekit.
Cet article a été initialement partagé sur r/mongodb et fait partie de mes notes techniques en cours lors du développement d’Ekit.
Discussion
- Comment gérez-vous les recherches rapides par préfixe à grande échelle dans MongoDB ?
- Avez-vous déjà comparé l’index slotting aux index wildcard pour des schémas dynamiques ?