ventajas - Formas de implementar el control de versiones de datos en MongoDB
que es mongodb (9)
Aquí hay otra solución que usa un solo documento para la versión actual y todas las versiones anteriores:
{
_id: ObjectId("..."),
data: [
{ vid: 1, content: "foo" },
{ vid: 2, content: "bar" }
]
}
data
contienen todas las versiones. La matriz de data
está ordenada , las nuevas versiones solo obtendrán $push
ed hasta el final de la matriz. data.vid
es el id de la versión, que es un número incremental.
Consigue la versión más reciente:
find(
{ "_id":ObjectId("...") },
{ "data":{ $slice:-1 } }
)
Consigue una versión específica por vid
:
find(
{ "_id":ObjectId("...") },
{ "data":{ $elemMatch:{ "vid":1 } } }
)
Devuelve solo los campos especificados:
find(
{ "_id":ObjectId("...") },
{ "data":{ $elemMatch:{ "vid":1 } }, "data.content":1 }
)
Insertar nueva versión: (y prevenir la inserción / actualización concurrente)
update(
{
"_id":ObjectId("..."),
$and:[
{ "data.vid":{ $not:{ $gt:2 } } },
{ "data.vid":2 }
]
},
{ $push:{ "data":{ "vid":3, "content":"baz" } } }
)
2
es el vid
de la versión más reciente actual y 3
es la nueva versión que se inserta. Como necesita el vid
la versión más reciente, es fácil obtener el siguiente vid
la versión: nextVID = oldVID + 1
.
El $and
condición asegurarán que 2
sea la última vid
.
De esta manera no hay necesidad de un índice único, pero la lógica de la aplicación debe encargarse de incrementar el vid
en la inserción.
Eliminar una versión específica:
update(
{ "_id":ObjectId("...") },
{ $pull:{ "data":{ "vid":2 } } }
)
¡Eso es!
(recuerda el límite de 16MB por documento)
¿Puede compartir sus opiniones sobre cómo implementaría el control de versiones de datos en MongoDB? (He hecho una pregunta similar con respecto a Cassandra . Si tiene alguna idea de qué db es mejor para eso, por favor comparta)
Supongamos que necesito versiones de registros en una libreta de direcciones simple. (Los registros de la libreta de direcciones se almacenan como objetos json planos). Espero que la historia:
- será utilizado con poca frecuencia
- se utilizarán todos a la vez para presentarlos en forma de "máquina del tiempo"
- No habrá más versiones que unos pocos cientos en un solo registro. la historia no expirará
Estoy considerando los siguientes enfoques:
Cree una nueva colección de objetos para almacenar el historial de registros o cambios en los registros. Almacenaría un objeto por versión con una referencia a la entrada de la libreta de direcciones. Tales registros se verían de la siguiente manera:
{ ''_id'': ''new id'', ''user'': user_id, ''timestamp'': timestamp, ''address_book_id'': ''id of the address book record'' ''old_record'': {''first_name'': ''Jon'', ''last_name'':''Doe'' ...} }
Este enfoque puede modificarse para almacenar un conjunto de versiones por documento. Pero esto parece ser un enfoque más lento sin ninguna ventaja.
Almacenar versiones como objeto serializado (JSON) adjunto a las entradas de la libreta de direcciones. No estoy seguro de cómo adjuntar tales objetos a los documentos de MongoDB. Tal vez como una serie de cadenas. ( Modelado después de la versión simple de documentos con CouchDB )
Existe un esquema de versiones llamado "Vermongo" que aborda algunos aspectos que no se han tratado en las otras respuestas.
Uno de estos problemas son las actualizaciones simultáneas, otro es la eliminación de documentos.
Vermongo almacena copias completas de documentos en una colección sombra. Para algunos casos de uso, esto podría causar una sobrecarga excesiva, pero creo que también simplifica muchas cosas.
He utilizado el siguiente paquete para un proyecto de meteor / MongoDB, y funciona bien, la principal ventaja es que almacena el historial / las revisiones dentro de una matriz en el mismo documento, por lo tanto, no es necesario contar con publicaciones o middleware adicionales para acceder al historial de cambios. . Puede admitir un número limitado de versiones anteriores (por ejemplo, las últimas diez versiones), también es compatible con la concatenación de cambios (por lo que todos los cambios ocurridos dentro de un período específico estarán cubiertos por una revisión).
nicklozon/meteor-collection-revisions
Otra opción de sonido es usar Meteor Vermongo ( here )
La primera gran pregunta cuando te sumerges en esto es "¿cómo quieres almacenar los conjuntos de cambios" ?
- Diffs?
- ¿Copias completas?
Mi enfoque personal sería almacenar diferencias. Debido a que la visualización de estas diferencias es realmente una acción especial, pondría las diferencias en una colección de "historia" diferente.
Yo usaría la colección diferente para ahorrar espacio de memoria. Por lo general, no desea un historial completo para una consulta simple. Por lo tanto, al mantener el historial fuera del objeto, también puede mantenerlo fuera de la memoria de acceso común cuando se consultan esos datos.
Para hacer mi vida más fácil, haría que un documento de historia contenga un diccionario de diferencias de fecha y hora. Algo como esto:
{
_id : "id of address book record",
changes : {
1234567 : { "city" : "Omaha", "state" : "Nebraska" },
1234568 : { "city" : "Kansas City", "state" : "Missouri" }
}
}
Para hacer mi vida realmente fácil, haría esta parte de mis DataObjects (EntityWrapper, lo que sea) que uso para acceder a mis datos. En general, estos objetos tienen algún tipo de historial, por lo que puede anular fácilmente el método save()
para realizar este cambio al mismo tiempo.
ACTUALIZACIÓN: 2015-10
Parece que ahora hay una especificación para manejar diferencias JSON . Esta parece ser una forma más robusta de almacenar las diferencias / cambios.
Otra opción es utilizar el plugin mongoose-history .
let mongoose = require(''mongoose'');
let mongooseHistory = require(''mongoose-history'');
let Schema = mongoose.Schema;
let MySchema = Post = new Schema({
title: String,
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.
Si está buscando una solución lista para rodar -
Mongoid ha construido en versiones simples
http://mongoid.org/en/mongoid/docs/extras.html#versioning
mongoid-history es un complemento de Ruby que proporciona una solución significativamente más complicada con auditoría, deshacer y rehacer
Si está utilizando mongoose, he encontrado que el siguiente complemento es una implementación útil del formato de parche JSON
Trabajé a través de esta solución que acomoda una versión publicada, borrador e histórica de los datos:
{
published: {},
draft: {},
history: {
"1" : {
metadata: <value>,
document: {}
},
...
}
}
Explico el modelo más aquí: http://software.danielwatrous.com/representing-revision-data-in-mongodb/
Para aquellos que pueden implementar algo como esto en Java , aquí hay un ejemplo:
http://software.danielwatrous.com/using-java-to-work-with-versioned-data/
Incluyendo todo el código que puedas bifurcar, si quieres.
Trate de usar Javers. Buena biblioteca