1

ブログ投稿用に次のドキュメント スキーマを使用する基本的なブログ Web アプリがあるとします。

{
    _id: ObjectId(...),
    title: "Blog Post #1",
    text: "<p>This is my blog post!</p>",
    comments: [
        {
            user: "username1",
            time: Date(...),
            text: "This is a great blog post!"
        },
        {
            user: "username2",
            time: Date(...),
            text: "This is even better than sliced bread!"
        }
    ]
}

これで問題ありませんが、ここで、ユーザーが自分のコメントを編集または削除できると仮定しましょう。その上、これは Web アプリなので、複数の人が同時にコメントを編集または削除する可能性があります。ここで、「username2」としてログインし、コメント配列の 2 番目の項目であるインデックス位置 1 であるコメントを編集しようとするとします。「保存」をクリックする直前に、user1 がログインし、1 番目のコメントを削除します。配列内のアイテム。私のコードがユーザー 2 のコメントをインデックス位置で削除しようとすると、配列に 2 つの項目がなくなるため失敗します。

2 つのアイデアが思い浮かびましたが、私はどちらにも夢中ではありません。

  • 各コメントに何らかの ID を作成する
  • 親ドキュメントに「lastModified」タイムスタンプを作成し、ドキュメントで何も変更されていない場合にのみ編集を保存します。

この種の状況を処理する最善の方法は何ですか? 各コメントに ID が本当に必要な場合、自分で生成する必要がありますか? どのデータ型にする必要がありますか? それとも、両方のアイデアを一緒に使用するのが最善でしょうか? それとも、私が考えていない別のオプションがありますか?

4

1 に答える 1

2

私の意見では、異なるライターを持つことは、ドキュメントを埋め込むことの主な欠点です。さまざまな解決策を提示するこのディスカッションをご覧になることをお勧めします。私は、1 つのドキュメントに複数のライターを使用することを避け、Comments代わりに別のコレクションを使用して、各コメントがその作成者によって所有されるようにします。インデックス化されたフィールドによって、投稿のすべてのコメントをpostIdかなり高速に取得できます。次に、コメントには通常の_idフィールドがあります。ObjectIdコメントが作成された時刻が自動的に保存され、デフォルトでは単調なインデックスであるため、を使用するのは理にかなっています。

親ドキュメントに「lastModified」タイムスタンプを作成し、ドキュメントで何も変更されていない場合にのみ編集を保存します。

これは「楽観的ロック」と呼ばれ、同時操作の可能性が高い場合は一般的に良くありません。ブログ投稿の場合、新しい投稿は古い投稿よりも多くのコメントを受け取る可能性が高いため、衝突の可能性はやや高いと言えます。

さらに別の厄介な副作用があります。たとえば、ブログ投稿の作成者がテキストを変更したいのに、その間に誰かがコメントを追加または削除したとします。$setこれで、ブログの作成者でさえ、テキストに対してアトミック操作を使用してバージョン チェックをバイパスしない限り、テキストを変更できなくなります。

于 2013-06-05T09:09:46.503 に答える