Façons d’implémenter la gestion des versions de données dans MongoDB

Pouvez-vous partager vos reflections sur la manière dont vous metsortingez en œuvre la gestion des versions de données dans MongoDB. (J’ai posé une question similaire à propos de Cassandra . Si vous avez des idées qui db est mieux pour cela, veuillez partager)

Supposons que je doive enregistrer des versions dans un carnet d’adresses simple. (Les enregistrements du carnet d’adresses sont stockés sous forme d’objects plats json). Je m’attends à ce que l’histoire:

  • sera utilisé rarement
  • sera utilisé tout à la fois pour le présenter de manière “time machine”
  • il n’y aura pas plus de versions que quelques centaines à un seul enregistrement. l’histoire n’expirera pas.

Je considère les approches suivantes:

La première grande question à poser est la suivante: “comment voulez-vous stocker les changesets” ?

  1. Diffs?
  2. Des copies entières?

Mon approche personnelle serait de stocker les diffs. Parce que l’affichage de ces diffs est vraiment une action spéciale, je placerais les diffs dans une collection “historique” différente.

J’utiliserais la collection différente pour économiser de l’espace mémoire. Vous ne voulez généralement pas un historique complet pour une requête simple. Ainsi, en gardant l’historique hors de l’object, vous pouvez également le garder hors de la mémoire communément utilisée lorsque ces données sont interrogées.

Pour faciliter ma vie, je ferais un document d’historique contenant un dictionnaire de diffs horodatés. Quelque chose comme ça:

{ _id : "id of address book record", changes : { 1234567 : { "city" : "Omaha", "state" : "Nearmka" }, 1234568 : { "city" : "Kansas City", "state" : "Missouri" } } } 

Pour rendre ma vie vraiment facile, je ferais cette partie de mes DataObjects (EntityWrapper, peu importe) que j’utilise pour accéder à mes données. En général, ces objects ont une forme d’histoire, de sorte que vous pouvez facilement remplacer la méthode save() pour effectuer cette modification en même temps.

MISE À JOUR: 2015-10

Il semble qu’il y ait maintenant une spécification pour gérer les diff JSON . Cela semble être un moyen plus robuste de stocker les diffs / modifications.

Il existe un système de gestion des versions appelé “Vermongo” qui aborde certains aspects qui n’ont pas été traités dans les autres réponses.

L’une de ces questions concerne les mises à jour simultanées, une autre consiste à supprimer des documents.

Vermongo stocke des copies complètes de documents dans une collection fantôme. Pour certains cas d’utilisation, cela pourrait entraîner trop de frais généraux, mais je pense que cela simplifie également beaucoup de choses.

https://github.com/thiloplanz/v7files/wiki/Vermongo

Voici une autre solution utilisant un seul document pour la version actuelle et toutes les anciennes versions:

 { _id: ObjectId("..."), data: [ { vid: 1, content: "foo" }, { vid: 2, content: "bar" } ] } 

data contiennent toutes les versions. Le tableau de data est ordonné , les nouvelles versions n’obtiendront que $push à la fin du tableau. data.vid est l’identifiant de la version, qui est un nombre incrémenté.

Obtenez la version la plus récente:

 find( { "_id":ObjectId("...") }, { "data":{ $slice:-1 } } ) 

Obtenez une version spécifique par vid :

 find( { "_id":ObjectId("...") }, { "data":{ $elemMatch:{ "vid":1 } } } ) 

Renvoie uniquement les champs spécifiés:

 find( { "_id":ObjectId("...") }, { "data":{ $elemMatch:{ "vid":1 } }, "data.content":1 } ) 

Insérer une nouvelle version: (et empêcher l’insertion / mise à jour simultanée)

 update( { "_id":ObjectId("..."), $and:[ { "data.vid":{ $not:{ $gt:2 } } }, { "data.vid":2 } ] }, { $push:{ "data":{ "vid":3, "content":"baz" } } } ) 

2 est la vid de la version la plus récente et 3 est la nouvelle version à insérer. Comme vous avez besoin de la version la plus récente de la version, il est facile de récupérer la vid de la prochaine version: nextVID = oldVID + 1 .

Le $and condition assureront que 2 est la dernière vid .

De cette façon, vous n’avez pas besoin d’un index unique, mais la logique de l’application doit faire en sorte d’incrémenter l’insertion vid .

Supprimer une version spécifique:

 update( { "_id":ObjectId("...") }, { $pull:{ "data":{ "vid":2 } } } ) 

C’est tout!

(rappelez-vous la limite de 16 Mo par document)

Si vous recherchez une solution prête à l’emploi –

Mongoid a construit en versioning simple

http://mongoid.org/en/mongoid/docs/extras.html#versioning

mongoid-history est un plugin Ruby qui fournit une solution beaucoup plus compliquée avec l’audit, l’annulation et la restauration

https://github.com/aq1018/mongoid-history

J’ai travaillé sur cette solution qui intègre une version publiée, une version brouillon et une version historique des données:

 { published: {}, draft: {}, history: { "1" : { metadata: , document: {} }, ... } } 

J’explique le modèle plus loin ici: http://software.danielwatrous.com/representing-revision-data-in-mongodb/

Pour ceux qui peuvent implémenter quelque chose comme ça en Java , voici un exemple:

http://software.danielwatrous.com/using-java-to-work-with-versenced-data/

Y compris tout le code que vous pouvez bifurquer, si vous voulez

https://github.com/dwatrous/mongodb-revision-objects

Si vous utilisez mongoose, le plug-in suivant est une implémentation utile du format JSON Patch

histoire de patch-mongoose

Une autre option consiste à utiliser le plugin mongoose-history .

 let mongoose = require('mongoose'); let mongooseHistory = require('mongoose-history'); let Schema = mongoose.Schema; let MySchema = Post = new Schema({ title: Ssortingng, status: Boolean }); MySchema.plugin(mongooseHistory); // The plugin will automatically create a new collection with the schema name + "_history". // In this case, collection with name "my_schema_history" will be created. 

J’ai utilisé le package ci-dessous pour un projet meteor / MongoDB, et cela fonctionne bien, le principal avantage est qu’il stocke l’historique / les révisions dans un tableau du même document, donc pas besoin de publications ou de middleware supplémentaires pour accéder à l’historique des modifications . Il peut prendre en charge un nombre limité de versions précédentes (par exemple, les dix dernières versions), il prend également en charge la concaténation des modifications (de sorte que toutes les modifications apscopes au cours d’une période donnée seront couvertes par une révision).

nicklozon / meteor-collection-révisions

Une autre option sonore consiste à utiliser Meteor Vermongo ( ici )

Essayez d’utiliser Javers. Bonne bibliothèque