Boa pergunta, eu também estava investigando isso.
Crie uma nova versão em cada alteração
Me deparei com o módulo Versioning do driver Mongoid para Ruby. Eu 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 a cada alteração , o que resultará em muito conteúdo duplicado sendo armazenado quando você estiver lidando com documentos grandes. Essa abordagem é boa quando você lida com documentos de tamanho pequeno e / ou não atualiza documentos com muita frequência.
Armazenar apenas alterações em uma nova versão
Outra abordagem seria armazenar apenas os campos alterados em uma nova versão . Em seguida, você pode 'achatar' seu histórico para reconstruir qualquer versão do documento. No entanto, isso é bastante complexo, pois você precisa acompanhar as alterações no modelo e armazenar as 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 planas.
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. No seu aplicativo, você não precisa controlar explicitamente as alterações, mas apenas crie uma nova versão da propriedade quando alterar seu valor. Um documento pode ser algo como isto:
{
_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 nivelada em uma coleção e os dados do histórico em uma coleção separada. Isso deve melhorar o tempo 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á executar duas consultas, em vez de uma. Portanto, a escolha de usar uma única coleção versus duas coleções separadas deve depender da frequência com que seu aplicativo precisa das versões históricas .
A maior parte dessa resposta é apenas um despejo cerebral de meus pensamentos, ainda não tentei nada disso. Olhando para trás, a primeira opção é provavelmente a melhor e mais fácil, a menos que a sobrecarga de dados duplicados seja muito significativa para o 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 o esforço de implementação, a menos que você não possa ir com a opção um.
Ansioso para feedback sobre isso, e soluções de outras pessoas para o problema :)