Une exigence assez courante dans les applications de base de données est de suivre les modifications apportées à une ou plusieurs entités spécifiques dans une base de données. J'ai entendu cela appelé gestion des versions de ligne, une table de journal ou une table d'historique (je suis sûr qu'il y a d'autres noms pour cela). Il existe un certain nombre de façons de l'aborder dans un SGBDR - vous pouvez écrire toutes les modifications de toutes les tables source dans une seule table (plus d'un journal) ou avoir une table d'historique distincte pour chaque table source. Vous avez également la possibilité de gérer la journalisation dans le code de l'application ou via des déclencheurs de base de données.
J'essaie de réfléchir à ce à quoi ressemblerait une solution au même problème dans une base de données NoSQL / document (en particulier MongoDB), et comment elle serait résolue de manière uniforme. Serait-ce aussi simple que de créer des numéros de version pour les documents et de ne jamais les écraser? Créer des collections séparées pour les documents «réels» et «enregistrés»? Comment cela affecterait-il les requêtes et les performances?
Quoi qu'il en soit, est-ce un scénario courant avec les bases de données NoSQL, et si oui, existe-t-il une solution commune?
Réponses:
Bonne question, je me suis aussi penché sur cette question.
Créer une nouvelle version à chaque changement
Je suis tombé sur le module de gestion des versions du pilote Mongoid pour Ruby. Je ne l'ai pas utilisé moi-même, mais d'après ce que j'ai pu trouver , il ajoute un numéro de version à chaque document. Les versions plus anciennes sont intégrées dans le document lui-même. L'inconvénient majeur est que le document entier est dupliqué à chaque modification , ce qui entraînera le stockage d'un grand nombre de contenu dupliqué lorsque vous traitez de gros documents. Cette approche convient cependant lorsque vous traitez avec des documents de petite taille et / ou que vous ne mettez pas à jour des documents très souvent.
Stocker uniquement les modifications dans une nouvelle version
Une autre approche consisterait à stocker uniquement les champs modifiés dans une nouvelle version . Ensuite, vous pouvez «aplatir» votre historique pour reconstruire n'importe quelle version du document. Ceci est cependant assez complexe, car vous devez suivre les modifications de votre modèle et stocker les mises à jour et les suppressions de manière à ce que votre application puisse reconstruire le document à jour. Cela peut être délicat, car vous avez affaire à des documents structurés plutôt qu'à des tables SQL plates.
Stocker les modifications dans le document
Chaque champ peut également avoir une histoire individuelle. Reconstruire des documents dans une version donnée est beaucoup plus facile de cette façon. Dans votre application, vous n'avez pas à suivre explicitement les modifications, mais créez simplement une nouvelle version de la propriété lorsque vous modifiez sa valeur. Un document pourrait ressembler à ceci:
Marquer une partie du document comme supprimée dans une version est cependant un peu gênant. Vous pouvez introduire un
state
champ pour les pièces qui peuvent être supprimées / restaurées à partir de votre application:Avec chacune de ces approches, vous pouvez stocker une version à jour et aplatie dans une collection et les données d'historique dans une collection distincte. Cela devrait améliorer les temps de requête si vous n'êtes intéressé que par la dernière version d'un document. Mais lorsque vous avez besoin à la fois de la dernière version et des données historiques, vous devrez effectuer deux requêtes au lieu d'une. Ainsi, le choix d'utiliser une seule collection plutôt que deux collections distinctes devrait dépendre de la fréquence à laquelle votre application a besoin des versions historiques .
La plupart de cette réponse n'est qu'une décharge cérébrale de mes pensées, je n'ai encore rien essayé de cela. En y repensant, la première option est probablement la solution la plus simple et la meilleure, à moins que la surcharge des données en double ne soit très importante pour votre application. La deuxième option est assez complexe et ne vaut probablement pas la peine. La troisième option est essentiellement une optimisation de l'option deux et devrait être plus facile à implémenter, mais ne vaut probablement pas l'effort d'implémentation à moins que vous ne puissiez vraiment pas opter pour l'option un.
Dans l'attente des commentaires à ce sujet et des solutions d'autres personnes au problème :)
la source
Nous l'avons partiellement implémenté sur notre site et nous utilisons le "Stocker les révisions dans un document séparé" (et une base de données séparée). Nous avons écrit une fonction personnalisée pour renvoyer les diffs et nous stockons cela. Pas si difficile et pouvons permettre une récupération automatisée.
la source
Pourquoi pas une variante des modifications du magasin dans le document ?
Au lieu de stocker des versions par rapport à chaque paire de clés, les paires de clés actuelles dans le document représentent toujours l'état le plus récent et un «journal» des modifications est stocké dans un tableau d'historique. Seules les clés qui ont changé depuis la création auront une entrée dans le journal.
la source
On peut avoir une base de données NoSQL actuelle et une base de données NoSQL historique. Il y aura un ETL tous les soirs. Cet ETL enregistrera chaque valeur avec un horodatage, donc au lieu de valeurs, ce sera toujours des tuples (champs versionnés). Il n'enregistrera une nouvelle valeur que si une modification a été apportée à la valeur actuelle, ce qui économise de l'espace dans le processus. Par exemple, ce fichier json de base de données NoSQL historique peut ressembler à ceci:
la source
Pour les utilisateurs de Python (python 3+, et plus bien sûr), il existe HistoricalCollection qui est une extension de l'objet Collection de pymongo.
Exemple tiré de la documentation:
Divulgation complète, je suis l'auteur du package. :)
la source