web-dev-qa-db-ja.com

データベースリンクリストは、mongodbを使用する場合の返信およびレビューシステムの優れたアーキテクチャですか?

ユーザーのレビューとレビューへの返信のシステムをウェブサイトで作成したいと考えています。返信への返信があります。私は重要な詳細だと思うmongodbデータベースを使用しています。

レビュードキュメントは、おおよそ次のようになります。

{
  review: {
    reviewid: String,
    userid: String,
    reviewRating: Int,
    reviewContent: String,
    replies: [Reply]
  }

}

返信オブジェクトは次のようになります。

{
  reply: {
    userid: String,
    reviewid: String,
    replyid: String,
    replyContent: String
  }
}

ユーザーの返信を保存する方法がわからない。一方では、レビュードキュメントに返信オブジェクトの配列を格納すると非常に便利です(1)。一方で、db(2)に返信を個別のドキュメントとして保存する方がより安定して整理されると思います。

ケース1では、mongodbの柔軟性の利点が得られ、dbルックアップを行う必要がなくなります。

ケース2では、各返信にprevious: ObjectIdおよびnext: ObjectIdフィールドを追加することを考えました。その後、レビューはチェーン内の最初の返信にのみリンクされます。ケース2では、常にnextを反復処理する必要があるため、返信の検索が増えます。 mongodbはデフォルトでidフィールドにインデックスを作成するため、次の応答を取得するのにそれほど時間がかかりません。別の欠点は、レビューごとの返信の数をカウントするために、カウントをレビューのフィールドとして保持し、毎回インクリメント/デクリメントすることを確認しない限り、返信の数と同じ数のdbルックアップを行う必要があることです。 (より複雑)。

つまり、最初のルートの方がパフォーマンスの点で優れています。それの主な欠点は、それが単なる配列であるという意味で、返信の順序が少し不安定であるということです。また、返信は自分のIDのないデータベース内の実際のドキュメントではないため、最初のルートは「薄っぺらな」ものだと本能的に感じています。

ここでのベストプラクティスについての提案を探しています。

1
Yos

レビューとともに保存するとスケーリングの問題が発生する可能性があるため、返信は独自のドキュメントとして保存する必要があります。これは整合性境界と呼ばれるDDDの重要な部分です。

複数のユーザーが互いに独立して返信を投稿できるようにしたいと思います。それらを一緒に保存している場合、別のユーザーが同時に意味のない返信を投稿したために、一部の返信が失敗する可能性があります。

また、レビューに対する返信が突然大量に発生した場合、システムは同じドキュメント内のおそらく1000件の返信を処理する必要があり、これも理想的ではありません。

3

私はEsbenに同意しますが、ドメインの観点からは、応答は個別のオブジェクトである必要がありますが、mongoについて具体的に質問します。mongoはまったく別の獣です。 mongoの場合、オブジェクトのストレージではなく、作成したクエリを見てデータベースを設計する必要があります。

つまり、レビューとその返信をクエリする必要がある場合、それらを1つのページに表示するには、必ず1つのオブジェクトに保存する必要があります。これは必ずしも、返信を保存するonlyの場所であることを意味するわけではありません。 (mongodbでは冗長性は問題ありません。これはnotリレーショナルデータベースです!)

あなたがまだ考えなければならないのは、単一のドキュメントが大きくなりすぎるとどうなるかです。 (まだ、ドキュメントあたり16 MBの制限があります。)一般的なパターンには、継続マーカーがあります。

{
    review: {
        reviewid: 00001,
        is_main_document: true,
        replies: [...],
        more_replies: 00002
},
{
    review: {
        reviewid: 00002,
        ismaindocument: false,
        replies: [...]
}

この原則は他の側面に続きます。例えば。返信オブジェクトにuseridがあります。ユーザーの名前と市を実際に表示したい場合は、user_nameuser_locationをそこに追加して、読み取り時に追加のデータベースラウンドトリップを実行する必要がないようにする必要があります。

ユーザーが別の都市に移動した場合、はい、おそらく1000ドキュメントを更新する必要があります。これはOKです。 mongoでは、通常の場合に最適化します。そして、ほとんどのWebアプリケーションの場合、これはつまり、実際のデータ変更よりも何百万倍も発生する通常の読み取りページインプレッションに対して最適化することを意味します。

もしあなたが今うんざりし始めたら(私が理解しているように、mongoから始めて私もそうしました)、2つの基本的な可能性があります:

  • 代わりにリレーショナルデータベースを使用する
  • 別のレイヤーを追加します。つまり、レビューと返信を別々のオブジェクト/コレクションに保持し、ビュー表示オブジェクトを追加します。ビューまたはプレゼンテーションオブジェクトは、レビューまたは返信のいずれかが変更されるたびに再構築します。
0
mtj