Pouvez-vous partager vos réflexions sur la manière d'implémenter le versionnage des 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 j'ai besoin de versionner des enregistrements dans un simple carnet d'adresses. (Les enregistrements du carnet d'adresses sont stockés en tant qu'objets json plats). J'attends que l'histoire:
- sera utilisé rarement
- sera utilisé d'un seul coup pour le présenter de façon "machine à remonter le temps"
- il n'y aura pas plus de versions que quelques centaines pour un seul enregistrement. l'histoire n'expirera pas.
J'envisage les approches suivantes:
Créez une nouvelle collection d'objets pour stocker l'historique des enregistrements ou les modifications apportées aux enregistrements. Il stockerait un objet par version avec une référence à l'entrée du carnet d'adresses. Ces enregistrements se présentent comme suit:
{ '_id': 'nouvel identifiant', 'user': user_id, 'timestamp': horodatage, 'address_book_id': 'id de l'enregistrement du carnet d'adresses' 'old_record': {'first_name': 'Jon', 'last_name': 'Doe' ...} }
Cette approche peut être modifiée pour stocker un tableau de versions par document. Mais cela semble être une approche plus lente sans aucun avantage.
Stockez les versions en tant qu'objet sérialisé (JSON) attaché aux entrées du carnet d'adresses. Je ne sais pas comment attacher de tels objets aux documents MongoDB. Peut-être comme un tableau de chaînes. ( Modélisé d'après la version de document simple avec CouchDB )
la source
Réponses:
La première grande question en plongeant dans ceci est "comment voulez-vous stocker les changesets" ?
Mon approche personnelle serait de stocker les différences. Parce que l'affichage de ces différences est vraiment une action spéciale, je mettrais les différences dans une autre collection "historique".
J'utiliserais les différentes collections pour économiser de l'espace mémoire. Vous ne voulez généralement pas d'historique complet pour une simple requête. Ainsi, en gardant l'historique hors de l'objet, vous pouvez également le garder hors de la mémoire couramment utilisée lorsque ces données sont interrogées.
Pour me faciliter la vie, je voudrais qu'un document historique contienne un dictionnaire de diff horodatés. Quelque chose comme ça:
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. Généralement, ces objets ont une certaine forme d'historique, de sorte que vous pouvez facilement remplacer la
save()
méthode pour effectuer cette modification en même temps.MISE À JOUR: 2015-10
Il semble qu'il existe maintenant une spécification pour gérer les différences JSON . Cela semble être un moyen plus robuste de stocker les différences / changements.
la source
changes
est vraiment facile:db.hist.update({_id: ID}, {$set { changes.12345 : CHANGES } }, true)
cela effectuera un upsert qui ne changera que les données requises. Mongo crée des documents avec "espace tampon" pour gérer ce type de changement. Il surveille également la façon dont les documents d'une collection changent et modifie la taille du tampon pour chaque collection. MongoDB est donc conçu pour exactement ce type de changement (ajouter une nouvelle propriété / pousser au tableau).Il existe un schéma de gestion des versions appelé "Vermongo" qui aborde certains aspects qui n'ont pas été traités dans les autres réponses.
L'un de ces problèmes concerne les mises à jour simultanées, un autre supprime les documents.
Vermongo stocke des copies complètes de documents dans une collection d'ombres. Pour certains cas d'utilisation, cela peut 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
la source
Voici une autre solution utilisant un seul document pour la version actuelle et toutes les anciennes versions:
data
contient toutes les versions. Ledata
tableau est ordonné , les nouvelles versions ne seront$push
éditées qu'à la fin du tableau.data.vid
est l'ID de version, qui est un nombre incrémentiel.Obtenez la version la plus récente:
Obtenez une version spécifique en
vid
:Renvoyer uniquement les champs spécifiés:
Insérer une nouvelle version: (et empêcher l'insertion / mise à jour simultanée)
2
est la versionvid
la plus récente et3
la nouvelle version est insérée. Parce que vous avez besoin de la version la plus récentevid
, il est facile de faire obtenir la prochaine version devid
:nextVID = oldVID + 1
.La
$and
condition assurera, c'est2
la dernièrevid
.De cette façon, il n'est pas nécessaire d'avoir un index unique, mais la logique d'application doit prendre soin d'incrémenter le
vid
insertion.Supprimer une version spécifique:
C'est tout!
(rappelez-vous la limite de 16 Mo par document)
la source
Si vous cherchez une solution prête à rouler -
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 audit, défaire et refaire
https://github.com/aq1018/mongoid-history
la source
J'ai travaillé sur cette solution qui héberge une version publiée, une ébauche et une version historique des données:
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-versioned-data/
Y compris tout le code que vous pouvez fork, si vous le souhaitez
https://github.com/dwatrous/mongodb-revision-objects
la source
Si vous utilisez mangouste, j'ai trouvé que le plugin suivant est une implémentation utile du format JSON Patch
histoire-patch-mangouste
la source
Une autre option consiste à utiliser le plugin mongoose-history .
la source
J'ai utilisé le package ci-dessous pour un projet météore / MongoDB, et cela fonctionne bien, le principal avantage est qu'il stocke l'historique / les révisions dans un tableau dans le 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 intervenues au cours d'une période spécifique seront couvertes par une révision).
nicklozon / meteor-collection-revisions
Une autre option sonore consiste à utiliser Meteor Vermongo ( ici )
la source