MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB/NoSQL :conserver l'historique des modifications de documents

Bonne question, j'étais moi-même en train de chercher moi-même.

Créer une nouvelle version à chaque modification

Je suis tombé sur le module Versioning 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 anciennes versions sont intégrées dans le document lui-même. L'inconvénient majeur est que l'intégralité du document est dupliqué à chaque modification , ce qui entraîne le stockage d'un grand nombre de contenus en double lorsque vous traitez des documents volumineux. Cette approche convient cependant lorsque vous traitez des documents de petite taille et/ou que vous ne mettez pas à jour les documents très souvent.

Ne stocker que les modifications dans une nouvelle version

Une autre approche serait de 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 un historique individuel. Reconstruire des documents à 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 :

{
  _id: "4c6b9456f61f000000007ba6"
  title: [
    { version: 1, value: "Hello world" },
    { version: 6, value: "Foo" }
  ],
  body: [
    { version: 1, value: "Is this thing on?" },
    { version: 2, value: "What should I write?" },
    { version: 6, value: "This is the new body" }
  ],
  tags: [
    { version: 1, value: [ "test", "trivial" ] },
    { version: 6, value: [ "foo", "test" ] }
  ],
  comments: [
    {
      author: "joe", // Unversioned field
      body: [
        { version: 3, value: "Something cool" }
      ]
    },
    {
      author: "xxx",
      body: [
        { version: 4, value: "Spam" },
        { version: 5, deleted: true }
      ]
    },
    {
      author: "jim",
      body: [
        { version: 7, value: "Not bad" },
        { version: 8, value: "Not bad at all" }
      ]
    }
  ]
}

Marquer une partie du document comme supprimée dans une version reste cependant quelque peu gênant. Vous pouvez introduire un state champ pour les parties qui peuvent être supprimées/restaurées depuis votre application :

{
  author: "xxx",
  body: [
    { version: 4, value: "Spam" }
  ],
  state: [
    { version: 4, deleted: false },
    { version: 5, deleted: true }
  ]
}

Avec chacune de ces approches, vous pouvez stocker une version mise à 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 devez effectuer deux requêtes au lieu d'une. Ainsi, le choix d'utiliser une seule collection ou deux collections distinctes doit dépendre de la fréquence à laquelle votre application a besoin des versions historiques .

La plupart de cette réponse n'est qu'un vidage cérébral de mes pensées, je n'ai encore rien essayé de tout cela. En y repensant, la première option est probablement la solution la plus simple et la meilleure, à moins que la surcharge de données en double ne soit très importante pour votre application. La deuxième option est assez complexe et n'en vaut probablement pas la peine. La troisième option est essentiellement une optimisation de l'option deux et devrait être plus facile à mettre en œuvre, mais ne vaut probablement pas l'effort de mise en œuvre à moins que vous ne puissiez vraiment pas choisir l'option un.

J'attends avec impatience les commentaires à ce sujet et les solutions d'autres personnes au problème :)