短いバージョン:ユーザーが編集可能なコンテンツを含むソーシャル Web アプリをモデレートするために、関係を追跡し、データを記録するデータベース バージョン管理システムを実装する方法についての提案を探しています。
長いバージョン:すべてのユーザーがコンテンツを編集できるソーシャル アプリを開発しています。例として、編集する項目の 1 つのタイプがBook
. ABook
は atitle
と a few (テーブルauthors
との多対多の関係) を持つことができます。authors
もちろん、この例はかなり単純です。実際のアイテムにはさらに多くのフィールドとリレーションがありますが、ルールは同じでなければなりません。
ここで、ユーザーによる変更を管理するためのバージョン管理システムを実装する必要があります。通常のユーザーと信頼できるユーザーの 2 つのユーザー グループがあるとします。通常のユーザーによる変更はログに記録されますが、モデレーターが特定の変更を受け入れるまでコミットされません。信頼できるユーザーが行った変更はすぐにコミットされますが、ログに記録されるため、いつでも元に戻すことができます。
例の a のリビジョンを保持するBook
場合、 との関係の変更を追跡する必要がありauthors
ます。リレーションの追加と削除を追跡し、元に戻すことができる必要があります。そのため、変更された場合はtitle
、変更を元に戻すことができる必要があります。への関係author
が削除された場合は、それを元に戻すことができる必要があります。また、何らかの関係が追加された場合は、それも元に戻すことができる必要があります。
アイテムとその関係を追跡する必要があるだけで、関連するものは何もありません。テーブルfoos
、bars
、およびがあればfoos_bars
、ロギングのみに関心がfoos
ありfoos_bars
、bars
はかなり独立したものになります。
私はこの素晴らしい質問に精通しており、それは一種の敵対的ソリューションであり、2番目のアプローチに関するかなり包括的な記事であり、フォローアップです。ただし、それらのいずれも、私の問題に対する明らかな答えとなる通常のテーブルデータと同様に、関係を追跡することについて特別な考慮を払っていません。
変更の一部のみを簡単に保持し、他の変更を元に戻すことができるため、すべての履歴に対して 1 つのテーブルを使用するアプローチが気に入っています。1 人のユーザーが フィールドA
とB
を送信し、次に 2 番目のユーザーが と を送信A
した場合のように、2 番目のユーザーの-changeB
だけを元に戻し、 . を保持するのは簡単です。他のアプローチでは多数のテーブルが必要になるのとは対照的に、機能全体に対して 1 つのテーブルを用意するのもよい方法です。また、誰が何をしたかを簡単に確認できます (例:フィールドのみを変更)。他の方法では簡単ではないようです。また、モデレーション プロセスを自動化する方が簡単なようです。必要なものはすべてリビジョン レコードに保存されるため、テーブル名を知る必要さえありません。B
A
foobar
トリガーの作成経験が限られている私が、リビジョンされたテーブルごとに 1 つのリビジョン テーブルというアプローチを使用する場合、編集を自動的に記録するシステムを実装することが可能であるか、または比較的簡単に実装できるかどうかはわかりません。 、ただし、何らかのパラメーターが設定されていない限り、すぐにはコミットしません (例: edit_from_trusted_user == true
)。そして、私が実際には望んでいないときにトリガーを呼び出すことを考えさせられます(たとえば、管理者によって行われた変更や、データを変更しようとする可能性のある他の「オブジェクト」にはモデレーションが適用されないため)。
どのソリューションを選択しても、id
すべての多対多リレーション テーブルにかなり人工的な を追加する必要があるように思われます ( の代わりに[book_id, author_id]
) [id, book_id, author_id]
。
次のように、1 つのテーブル アプローチでリレーションを実装することを考えました。標準のリビジョン テーブル構造がある場合
[ID] [int]
[TableName] [varchar]
[RecordID] [int]
[FieldName] [varchar]
[OldValue] [varchar]
[NewValue] [varchar]
[EventType] [enum]
[EventDate] [datetime]
[UserID] [int]
リレーションの外部キーに and を、orを、 andRecordID
をFieldName
にNULL
設定するだけで、リレーションを保存できEventType
ます。唯一の問題は、私のリレーションの一部には追加のデータ (グラフのエッジの重みなど) があるため、それもどこかに保存する必要があることです。繰り返しになりますが、新しいリレーションを追加する操作は 2 つのイベント シーケンスに分割できます: ADD と SET(weight) ですが、人工的なリレーションが必要になり、そのような解決策に問題がないかどうかはわかりません。将来への影響。ADD
DELETE
OldValue
NewValue
ID
約 5 から 10 のバージョン管理されたテーブルがあり、それぞれに追跡する多対多のリレーションが平均 3 つあります。私は InnoDB で MySQL を使用しています。アプリは PHP 5.3 で作成され、PDO を使用してデータベースに接続されています。データベース トリガーの代わりにアプリ ロジックにバージョニングを配置しても問題ありません。全体が機能し、合理的に効率的である必要があります。編集に比べて元に戻すことはめったに発生しないと思います。また、コンテンツのビュー数に比べて編集はほとんどありません。モデレーターのみがリビジョン データにアクセスして、最近の変更を承認または拒否します。
そのようなシステムを実装した経験はありますか? この問題に対する推奨される解決策は何ですか? 心に浮かぶ考慮事項はありますか?
私は SO とネットをかなり長い間検索しましたが、問題を解決するのに役立つものは何も見つかりませんでした。ただし、何かを見逃した場合は、リンクや指示に感謝します。
ありがとう。