Você pode compartilhar seus pensamentos como implementaria a versão de dados no MongoDB. (Eu fiz uma pergunta semelhante a respeito de Cassandra . Se você tem alguma idéia de qual db é melhor para isso, compartilhe)
Suponha que eu precise atualizar os registros em um catálogo de endereços simples. (Os registros do catálogo de endereços são armazenados como objetos json simples). Espero que a história:
- será usado com pouca frequência
- será usado de uma só vez para apresentá-lo de forma "máquina do tempo"
- não haverá mais versões do que algumas centenas para um único registro. a história não vai expirar.
Estou considerando as seguintes abordagens:
Crie uma nova coleção de objetos para armazenar o histórico de registros ou alterações nos registros. Ele armazenaria um objeto por versão com uma referência à entrada do catálogo de endereços. Esses registros teriam a seguinte aparência:
{ '_id': 'novo ID', 'usuário': user_id, 'timestamp': timestamp, 'address_book_id': 'identificação do registro do catálogo de endereços' 'old_record': {'first_name': 'Jon', 'last_name': 'Doe' ...} }
Essa abordagem pode ser modificada para armazenar uma matriz de versões por documento. Mas essa parece ser uma abordagem mais lenta, sem vantagens.
Armazene versões como objeto serializado (JSON) anexado às entradas do catálogo de endereços. Não sei como anexar esses objetos aos documentos do MongoDB. Talvez como uma série de strings. ( Modelado após o Simple Document Versioning com CouchDB )
fonte
Respostas:
A primeira grande questão ao abordar isso é "como você deseja armazenar conjuntos de alterações" ?
Minha abordagem pessoal seria armazenar diferenças. Como a exibição dessas diferenças é realmente uma ação especial, eu as colocaria em uma coleção diferente de "histórico".
Eu usaria a coleção diferente para economizar espaço de memória. Você geralmente não deseja um histórico completo para uma consulta simples. Portanto, mantendo o histórico fora do objeto, você também pode mantê-lo fora da memória geralmente acessada quando esses dados são consultados.
Para facilitar minha vida, eu faria um documento histórico conter um dicionário de diferenças de data e hora. Algo assim:
Para facilitar minha vida, eu faria essa parte dos meus DataObjects (EntityWrapper, qualquer que seja) que eu uso para acessar meus dados. Geralmente esses objetos têm alguma forma de histórico, para que você possa substituir facilmente o
save()
método para fazer essa alteração ao mesmo tempo.ATUALIZAÇÃO: 2015-10
Parece que agora há uma especificação para lidar com diferenças JSON . Essa parece ser uma maneira mais robusta de armazenar as diferenças / alterações.
fonte
changes
é realmente fácil:db.hist.update({_id: ID}, {$set { changes.12345 : CHANGES } }, true)
isso fará uma subida que alterará apenas os dados necessários. O Mongo cria documentos com "espaço no buffer" para lidar com esse tipo de alteração. Ele também observa como os documentos em uma coleção são alterados e modificam o tamanho do buffer de cada coleção. Portanto, o MongoDB foi projetado para exatamente esse tipo de alteração (adicione nova propriedade / push à matriz).Existe um esquema de controle de versão chamado "Vermongo", que aborda alguns aspectos que não foram tratados nas outras respostas.
Um desses problemas é atualizações simultâneas, outro está excluindo documentos.
O Vermongo armazena cópias completas de documentos em uma coleção de sombras. Para alguns casos de uso, isso pode causar muita sobrecarga, mas acho que também simplifica muitas coisas.
https://github.com/thiloplanz/v7files/wiki/Vermongo
fonte
Aqui está outra solução usando um único documento para a versão atual e todas as versões antigas:
data
contém todas as versões. Adata
matriz é ordenada , novas versões serão editadas apenas$push
no final da matriz.data.vid
é o ID da versão, que é um número incremental.Obtenha a versão mais recente:
Obtenha uma versão específica
vid
:Retorne apenas os campos especificados:
Inserir nova versão: (e impedir inserção / atualização simultânea)
2
é avid
versão mais recente atual e3
a nova versão está sendo inserida. Como você precisa das versões mais recentesvid
, é fácil obter as próximas versõesvid
:nextVID = oldVID + 1
.A
$and
condição garantirá, que2
é o mais recentevid
.Dessa forma, não há necessidade de um índice exclusivo, mas a lógica do aplicativo precisa cuidar do incremento da
vid
inserção on.Remova uma versão específica:
É isso aí!
(lembre-se dos 16 MB por limite de documento)
fonte
Se você está procurando uma solução pronta para uso,
O Mongoid criou versões simples
http://mongoid.org/en/mongoid/docs/extras.html#versioning
mongoid-history é um plugin Ruby que fornece uma solução significativamente mais complicada com auditoria, desfazer e refazer
https://github.com/aq1018/mongoid-history
fonte
Eu trabalhei com essa solução que acomoda versões publicadas, de rascunho e históricas dos dados:
Eu explico mais o modelo aqui: http://software.danielwatrous.com/representing-revision-data-in-mongodb/
Para aqueles que podem implementar algo parecido com isto em Java , aqui está um exemplo:
http://software.danielwatrous.com/using-java-to-work-with-versioned-data/
Incluindo todo o código que você pode bifurcar, se quiser
https://github.com/dwatrous/mongodb-revision-objects
fonte
Se você estiver usando o mongoose, achei o seguinte plugin uma implementação útil do formato JSON Patch
mongoose-patch-history
fonte
Outra opção é usar o plugin mongoose-history .
fonte
Eu usei o pacote abaixo para um projeto meteoro / MongoDB e funciona bem, a principal vantagem é que ele armazena histórico / revisões em uma matriz no mesmo documento, portanto, não há necessidade de publicações ou middleware adicionais para acessar o histórico de alterações . Ele pode suportar um número limitado de versões anteriores (por exemplo, últimas dez versões), também suporta concatenação de alterações (todas as alterações ocorridas dentro de um período específico serão cobertas por uma revisão).
nicklozon / revisão de coleções de meteoros
Outra opção de som é usar o Meteor Vermongo ( aqui )
fonte