4

リレーショナル データベースでは、1-n nn の関係は 2 つ以上のテーブルを意味します。しかし、mongoDB では、これらのものを次のように 1 つのモデルに直接格納できるため、次のようになります。

Article{
  content: String, 
  uid: String,
  comments:[Comment]
}

それらの関係を管理する方法について混乱しています。たとえば、article-comments モデルでは、すべてのコメントを直接 article モデルに保存し、毎回 article オブジェクト全体を JSON に読み込む必要がありますか? しかし、コメントが非常に大きくなった場合はどうなるでしょうか。たとえば、記事オブジェクトに 1,000 のコメントがある場合、そのような戦略では GET プロセスが毎回非常に遅くなりますか?

4

4 に答える 4

1

私は決してこれに関する専門家ではありませんが、以前に同様の状況を経験したことがあります。

私が見たいくつかのデモから、はい、すべてのコメントを直接行に保存する必要があります。これにより、最高のパフォーマンスが得られます (とてつもない量のコメントが予想される場合を除きます)。このようにして、ドキュメントにすべてが含まれます。

将来、物事が順調に進み始め、物事が遅くなっていくことに気付いた場合、いくつかのことを行うことができます。他のコメントが保存されている場所への参照を使用して、最新の (任意の数を挿入する) コメントを保存し、古いコメントを「バケット」にマップ削減して、読み込み時間を高速に保つことができます。

ただし、最初は 1 つのドキュメントに保存します。

したがって、おそらく次のようなモデルになります。

Article{    
    content: String, 
    uid: String,
    comments:[
        {"comment":"hi", "user":"jack"},
        {"comment":"hi", "user":"jack"},
    ]
    "oldCommentsIdentifier":12345
}

次に、コメントをコメント文字列から移動した場合にのみ、oldCommentsIdentifier を設定しますが、1000 未満のコメント、場合によってはそれ以上のコメントに対しては、実際にはこれを行いません。「スイート」スポットが何であるかを確認するには、ここで少しテストする必要があります。

于 2012-12-05T22:14:59.517 に答える
0

これを行う最善の方法はありません。MongoDBでは、コレクションを使用するアプリケーションに応じてコレクションを設計する必要があります。

アプリケーションで記事付きのコメントを表示する必要がある場合は、これらのコメントを記事コレクションに埋め込む方がよいと言えます。そうしないと、データベースへのラウンドトリップが数回発生することになります。

埋め込みが機能しないシナリオが1つあります。私の知る限り、MongoDBではドキュメントサイズは16MBに制限されています。これは実際にはかなり大きいです。ただし、ドキュメントサイズがこの制限を超える可能性があると思われる場合は、個別のコレクションを用意することをお勧めします。

于 2012-12-06T09:31:03.807 に答える
0

でも記事とコメントを _id で紐づけてこの問題を解決すると、ちょっとリレーショナルデータベースの設計に逆戻りしませんか?そしてどういうわけか NoSQL であることの本質を失いますか?

そうではありませんが、NoSQL はモデルを埋め込むことだけがすべてではありません。実際、シナリオでは埋め込みを慎重に検討する必要があります。

ドキュメント自体として使用する必要があるオブジェクトを埋め込むことで発生する可能性のある問題のかなりの数が、集約フレームワークによって解決されることは事実です。ドキュメントとして使用する必要があるサブドキュメントを次のように定義します。

  • インターフェイスでページングする必要があるドキュメント
  • 複数のルート ドキュメントにまたがって存在する可能性があるドキュメント
  • グループ内で高度な並べ替えが必要なドキュメント
  • グループ内でルート ドキュメントの 16 MB の制限を超えるドキュメント

私が言ったように、集約フレームワークはこれを少し解決しますが、リアルタイムまたはほぼ同じ数のドキュメントに対してSQLで同じことを実行するのと同じように、クエリを実行しようとしています。

この効果は常に望ましいとは限りません。

$slice 演算子を使用して、通常のクエリでサブドキュメントのページング (一種) を実現できますが、これには、大きな結果セットを使用skip()した場合とほとんど同じ問題が発生する可能性があります。limit()範囲クエリ (集計フレームワークが再び必要になります)。1000 個のサブドキュメントがあっても、私だけでなく他の人にも速度の問題が見られました。

それでは、元の質問に戻りましょう: スキーマを管理する方法です。

さて、あなたが好まない答えは次のとおりです。それはすべて依存します。

あなたのコメントは、分離すべきニーズを満たしていますか? そうであれば、それはおそらく良い賭けです。

于 2012-12-06T08:33:45.593 に答える
0

I think a large part of the answer depends on how many comments you are expecting. Having a document that contains an array that could grow to an arbitrarily large size is a bad idea, for a couple reasons. First, the $push operator tends to be slow because it often increases the size of the document, forcing it to be moved. Second, there is a maximum BSON size of 16MB, so eventually you will not be able to grow the array any more.

If you expect each article to have a large number of comments, you could create a separate "comments" collection, where each document has an "article_id" field that contains the _id of the article that it is tied to (or the uid, or some other field unique to the article). This would make retrieving all comments for a specific article easy, by querying the "comments" collection for any documents whose "article_id" field matches the article's _id. Indexing this field would make the query very fast.

The link that limelights posted as a comment on your question is also a great reference for general tips about schema design.

于 2012-12-05T22:33:14.763 に答える