良い質問です。私もこれを調べていました。
変更ごとに新しいバージョンを作成する
Ruby用のMongoidドライバーのバージョニングモジュールに出くわしました。自分で使ったことはありませんが、見つけたところから、各ドキュメントにバージョン番号が追加されています。古いバージョンはドキュメント自体に埋め込まれています。主な欠点は、変更のたびにドキュメント全体が複製されることです。 、これにより、大きなドキュメントを処理するときに多くの重複コンテンツが保存されます。ただし、このアプローチは、小さいサイズのドキュメントを処理している場合や、ドキュメントを頻繁に更新しない場合には問題ありません。
変更を新しいバージョンにのみ保存する
別のアプローチは、変更されたフィールドのみを新しいバージョンに保存することです。 。次に、履歴を「フラット化」して、ドキュメントの任意のバージョンを再構築できます。ただし、アプリケーションが最新のドキュメントを再構築できるように、モデルの変更を追跡し、更新と削除を保存する必要があるため、これはかなり複雑です。フラットなSQLテーブルではなく構造化されたドキュメントを扱っているため、これは注意が必要な場合があります。
変更をドキュメント内に保存する
各フィールドには、個別の履歴を含めることもできます。この方法では、ドキュメントを特定のバージョンに再構築する方がはるかに簡単です。アプリケーションでは、変更を明示的に追跡する必要はありませんが、値を変更するときにプロパティの新しいバージョンを作成するだけです。ドキュメントは次のようになります:
{
_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" }
]
}
]
}
ただし、あるバージョンでドキュメントの一部を削除済みとしてマークするのは、まだやや厄介です。 state
を導入できます アプリケーションから削除/復元できるパーツのフィールド:
{
author: "xxx",
body: [
{ version: 4, value: "Spam" }
],
state: [
{ version: 4, deleted: false },
{ version: 5, deleted: true }
]
}
これらの各アプローチを使用すると、最新のフラット化されたバージョンを1つのコレクションに保存し、履歴データを別のコレクションに保存できます。これにより、ドキュメントの最新バージョンのみに関心がある場合は、クエリ時間が短縮されます。ただし、最新バージョンと履歴データの両方が必要な場合は、1つではなく2つのクエリを実行する必要があります。したがって、単一のコレクションを使用するか、2つの別々のコレクションを使用するかの選択は、アプリケーションが履歴バージョンを必要とする頻度に依存する必要があります。 。
この答えのほとんどは私の考えの単なる頭脳のダンプです、私はまだこれのどれも実際に試していません。振り返ってみると、重複データのオーバーヘッドがアプリケーションにとって非常に重要でない限り、最初のオプションがおそらく最も簡単で最良のソリューションです。 2番目のオプションは非常に複雑で、おそらく努力する価値はありません。 3番目のオプションは、基本的にオプション2の最適化であり、実装が簡単なはずですが、オプション1を実際に使用できない場合を除いて、実装に取り組む価値はないでしょう。
これに関するフィードバック、および問題に対する他の人々の解決策を楽しみにしています:)