Um requisito bastante comum em aplicativos de banco de dados é rastrear alterações em uma ou mais entidades específicas em um banco de dados. Eu ouvi isso chamado versionamento de linha, uma tabela de log ou uma tabela de histórico (tenho certeza que existem outros nomes para ela). Existem várias maneiras de abordá-lo em um RDBMS - você pode gravar todas as alterações de todas as tabelas de origem em uma única tabela (mais de um log) ou ter uma tabela de histórico separada para cada tabela de origem. Você também tem a opção de gerenciar o logon no código do aplicativo ou por meio de gatilhos de banco de dados.
Estou tentando pensar em como seria uma solução para o mesmo problema em um banco de dados NoSQL / documento (especificamente o MongoDB) e como seria resolvida de maneira uniforme. Seria tão simples quanto criar números de versão para documentos e nunca substituí-los? Criando coleções separadas para documentos "reais" vs. "registrados"? Como isso afetaria a consulta e o desempenho?
Enfim, esse é um cenário comum com os bancos de dados NoSQL e, em caso afirmativo, existe uma solução comum?
Respostas:
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:
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: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 :)
fonte
Implementamos isso parcialmente em nosso site e usamos as 'Revisões da loja em um documento separado "(e banco de dados separado). Escrevemos uma função personalizada para retornar as diferenças e armazenamos isso. Não é tão difícil e pode permitir a recuperação automatizada.
fonte
Por que não uma variação na loja muda dentro do documento ?
Em vez de armazenar versões em cada par de chaves, os pares de chaves atuais no documento sempre representam o estado mais recente e um 'log' de alterações é armazenado em uma matriz de histórico. Somente as chaves que foram alteradas desde a criação terão uma entrada no log.
fonte
Pode-se ter um banco de dados NoSQL atual e um banco de dados NoSQL histórico. Haverá um ETL noturno executado todos os dias. Esse ETL registrará todos os valores com um carimbo de data / hora; portanto, em vez de valores, sempre serão tuplas (campos com versão). Ele só registrará um novo valor se houver uma alteração no valor atual, economizando espaço no processo. Por exemplo, esse arquivo json histórico do banco de dados NoSQL pode ter a seguinte aparência:
fonte
Para usuários de Python (python 3+ e, é claro), existe o HistoricalCollection que é uma extensão do objeto Collection do pymongo.
Exemplo dos documentos:
Divulgação completa, eu sou o autor do pacote. :)
fonte