Formas de implementar el control de versiones de datos en MongoDB


Puede compartir sus pensamientos ¿cómo implementar el control de versiones de datos en MongoDB. (He hecho una pregunta similar con respecto a Cassandra. Si usted tiene algún pensamiento que db es mejor para que por favor compartir)

Supongamos que necesito versionar los registros en una simple libreta de direcciones. (Los registros de la libreta de direcciones se almacenan como objetos json planos). Espero que la historia:

  • se utilizará con poca frecuencia
  • se utilizará todo a la vez para presentarlo en una " máquina del tiempo" moda
  • no habrá más versiones que unos pocos cientos a un solo registro. la historia no caducará.

Estoy considerando los siguientes enfoques:

  • Cree una nueva colección de objetos para almacenar el historial de registros o los 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ía como sigue:

    {
     '_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 se puede modificar para almacenar una matriz de versiones por documento. Pero esto parece ser un enfoque más lento sin ninguna ventaja.

  • Almacene las 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 MongoDB. Tal vez como una matriz de cuerdas. ( Modelado según Versiones Simples de Documentos con CouchDB)

Author: Community, 2010-11-15

9 answers

La primera gran pregunta cuando se sumerge en esto es "¿cómo desea almacenar conjuntos de cambios"?

  1. ¿Diferencias?
  2. Copias de discos enteros?

Mi enfoque personal sería almacenar diferencias. Debido a que la visualización de estos diffs es realmente una acción especial, pondría los diffs en una colección de "historia" diferente.

Usaría la colección diferente para ahorrar espacio de memoria. Por lo general, no desea un historial completo para una consulta simple. Así que manteniendo la historial fuera del objeto también puede mantenerlo fuera de la memoria a la que se accede comúnmente cuando se consultan esos datos.

Para facilitar mi vida, haría un documento de historia que contuviera un diccionario de diferencias con marcas de tiempo. 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. Generalmente estos objetos tienen alguna forma de historia, por lo que puede anular fácilmente el método save() para hacer esto cambiar al mismo tiempo.

ACTUALIZAR: 2015-10

Parece que ahora hay una especificación para manejar los diferenciales JSON. Esto parece una forma más robusta de almacenar los diffs / cambios.

 133
Author: Gates VP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-27 18:16:27

Hay un esquema de versionado 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 shadow. Para algunos casos de uso esto podría causar demasiada sobrecarga, pero creo que también simplifica muchas cosas.

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

 27
Author: Marian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-16 12:27:23

Aquí hay otra solución que utiliza 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 contiene todas las versiones. El array dataes ordenado, las nuevas versiones solo obtendrán $push ed al final del array. data.vid es el id de la versión, que es un número incremental.

Obtenga la versión más reciente:

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

Obtener una versión específica por vid:

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

Devolver solo especificado campos:

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

Insertar nueva versión: (y evitar insertar/actualizar simultáneamente)

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. Debido a que necesita la versión más reciente vid, es fácil obtener la siguiente versión vid: nextVID = oldVID + 1.

La condición $and asegurará que 2 sea la última vid.

De esta manera no hay necesidad de un índice único, pero la aplicación logic tiene que cuidar de incrementar el vid en insert.

Eliminar una versión específica:

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

¡Eso es todo!

(recuerde el límite de 16 MB por documento)

 14
Author: Benjamin M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-14 17:53:04

Si está buscando una solución lista para rodar-

Mongoid ha construido un versionado simple

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

Mongoid-history es un plugin de Ruby que proporciona una solución significativamente más complicada con la auditoría, deshacer y rehacer

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

 11
Author: s01ipsist,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-13 09:03:11

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 adelante 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 se puede bifurcar, si te gusta

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

 7
Author: Daniel Watrous,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-09 15:42:06

Si está usando mangosta, he encontrado que el siguiente complemento es una implementación útil del formato JSON Patch

Mangosta-parche-historia

 2
Author: bmw15,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-10 16:10:51

Otra opción es usar 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.
 0
Author: Muhammad Reda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-21 17:42:32

He utilizado el siguiente paquete para un proyecto meteor/MongoDB, y funciona bien, la principal ventaja es que almacena el historial/revisiones dentro de un array en el mismo documento, por lo tanto no hay necesidad de publicaciones adicionales o middleware para acceder al historial de cambios. Puede soportar un número limitado de versiones anteriores (ej. ú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 serán cubiertos por uno revision).

Nicklozon / meteor-collection-revisions

Otra opción de sonido es usar Meteor Vermongo (aquí )

 0
Author: helcode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-25 07:28:31

Intenta usar Javers. Buena biblioteca.

 -2
Author: Demel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-12 08:20:01