Dobrá otázka, sám jsem se tím také zabýval.
Při každé změně vytvořte novou verzi
Narazil jsem na modul Versioning ovladače Mongoid pro Ruby. Sám jsem to nepoužil, ale podle toho, co jsem našel, přidává ke každému dokumentu číslo verze. Starší verze jsou vloženy do samotného dokumentu. Hlavní nevýhodou je, že při každé změně je celý dokument duplikován , což bude mít za následek ukládání velkého množství duplicitního obsahu, když pracujete s velkými dokumenty. Tento přístup je však v pořádku, když pracujete s dokumenty malé velikosti a/nebo dokumenty příliš často neaktualizujete.
Ukládat změny pouze v nové verzi
Dalším přístupem by bylo uložení pouze změněných polí v nové verzi . Poté můžete „narovnat“ svou historii a rekonstruovat jakoukoli verzi dokumentu. To je však poměrně složité, protože potřebujete sledovat změny ve svém modelu a ukládat aktualizace a smazání takovým způsobem, aby vaše aplikace mohla rekonstruovat aktuální dokument. To může být složité, protože se zabýváte spíše strukturovanými dokumenty než plochými tabulkami SQL.
Uložte změny v dokumentu
Každý obor může mít také individuální historii. Rekonstrukce dokumentů na danou verzi je tímto způsobem mnohem jednodušší. Ve své aplikaci nemusíte explicitně sledovat změny, ale stačí vytvořit novou verzi vlastnosti, když změníte její hodnotu. Dokument může vypadat nějak takto:
{
_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" }
]
}
]
}
Označení části dokumentu jako smazané ve verzi je však stále poněkud nepříjemné. Můžete zavést state
pole pro díly, které lze z vaší aplikace odstranit/obnovit:
{
author: "xxx",
body: [
{ version: 4, value: "Spam" }
],
state: [
{ version: 4, deleted: false },
{ version: 5, deleted: true }
]
}
S každým z těchto přístupů můžete uložit aktuální a sloučenou verzi do jedné kolekce a data historie do samostatné kolekce. To by mělo zlepšit časy dotazování, pokud vás zajímá pouze nejnovější verze dokumentu. Když však potřebujete nejnovější verzi i historická data, budete muset zadat dva dotazy, nikoli jeden. Volba použití jedné kolekce nebo dvou samostatných kolekcí by tedy měla záviset na tom, jak často vaše aplikace potřebuje historické verze .
Většina z této odpovědi je jen výsypka mých myšlenek, ve skutečnosti jsem nic z toho ještě nezkoušel. Když se na to podíváme zpětně, první možnost je pravděpodobně nejjednodušší a nejlepší řešení, pokud není režie duplicitních dat pro vaši aplikaci velmi významná. Druhá možnost je poměrně složitá a pravděpodobně nestojí za námahu. Třetí možnost je v podstatě optimalizací možnosti dvě a měla by být snadněji implementovatelná, ale pravděpodobně nestojí za námahu při implementaci, pokud opravdu nemůžete použít možnost jedna.
Těšíme se na zpětnou vazbu a řešení problému od ostatních :)