Boa pergunta, eu também estava pesquisando sobre isso.
Crie uma nova versão a cada alteração
Me deparei com o módulo Versioning do driver Mongoid para Ruby. Eu mesmo não o usei, mas pelo que pude encontrar, ele adiciona um número de versão a cada documento. As versões mais antigas são incorporadas no próprio documento. A principal desvantagem é que todo o documento é duplicado em cada alteração , o que resultará no armazenamento de muito conteúdo duplicado quando você estiver lidando com documentos grandes. Essa abordagem é boa quando você está lidando com documentos de tamanho pequeno e/ou não atualiza os documentos com muita frequência.
Armazenar apenas as alterações em uma nova versão
Outra abordagem seria armazenar apenas os campos alterados em uma nova versão . Então você pode 'achatar' seu histórico para reconstruir qualquer versão do documento. No entanto, isso é bastante complexo, pois você precisa rastrear alterações em seu modelo e armazenar atualizações e exclusões de forma que seu aplicativo possa reconstruir o documento atualizado. Isso pode ser complicado, pois você está lidando com documentos estruturados em vez de tabelas SQL simples.
Armazenar alterações no documento
Cada campo também pode ter um histórico individual. Reconstruir documentos para uma determinada versão é muito mais fácil dessa maneira. Em seu aplicativo, você não precisa rastrear explicitamente as alterações, mas apenas criar uma nova versão da propriedade quando alterar seu valor. Um documento pode ser algo assim:
{
_id: "4c6b9456f61f000000007ba6"
title: [
{ version: 1, value: "Hello world" },
{ version: 6, value: "Foo" }
],
body: [
{ version: 1, value: "Is this thing on?" },
{ version: 2, value: "What should I write?" },
{ version: 6, value: "This is the new body" }
],
tags: [
{ version: 1, value: [ "test", "trivial" ] },
{ version: 6, value: [ "foo", "test" ] }
],
comments: [
{
author: "joe", // Unversioned field
body: [
{ version: 3, value: "Something cool" }
]
},
{
author: "xxx",
body: [
{ version: 4, value: "Spam" },
{ version: 5, deleted: true }
]
},
{
author: "jim",
body: [
{ version: 7, value: "Not bad" },
{ version: 8, value: "Not bad at all" }
]
}
]
}
Marcar parte do documento como excluído em uma versão ainda é um pouco estranho. Você pode introduzir um
state
campo para peças que podem ser excluídas/restauradas do seu aplicativo:{
author: "xxx",
body: [
{ version: 4, value: "Spam" }
],
state: [
{ version: 4, deleted: false },
{ version: 5, deleted: true }
]
}
Com cada uma dessas abordagens, você pode armazenar uma versão atualizada e simplificada em uma coleção e os dados do histórico em uma coleção separada. Isso deve melhorar os tempos de consulta se você estiver interessado apenas na versão mais recente de um documento. Mas quando você precisar da versão mais recente e dos dados históricos, precisará realizar duas consultas, em vez de uma. Portanto, a escolha de usar uma única coleção em vez de duas coleções separadas deve depender de com que frequência seu aplicativo precisa das versões históricas .
A maior parte dessa resposta é apenas um despejo do cérebro dos meus pensamentos, na verdade ainda não tentei nada disso. Olhando para trás, a primeira opção é provavelmente a solução mais fácil e melhor, a menos que a sobrecarga de dados duplicados seja muito significativa para seu aplicativo. A segunda opção é bastante complexa e provavelmente não vale o esforço. A terceira opção é basicamente uma otimização da opção dois e deve ser mais fácil de implementar, mas provavelmente não vale a pena o esforço de implementação, a menos que você realmente não possa ir com a opção um.
Aguardo feedback sobre isso e as soluções de outras pessoas para o problema :)