2011-03-07 12 views
26

ドキュメントベースのデータベース(mongodb)を使用してブログのようなサイトのスキーマをどのように設計しますか?このサイトには、User、Article、Commentというオブジェクトがあります。ユーザーは記事にコメントを追加できます。各ユーザーは、コメントごとに1回だけ投票することもできます。ブログのmongodbスキーマデザイン

私は効率的にこれらのクエリを行うことができるようにしたい:
1条Aを取得し、条Aおよびコメント
2あたり票の#のコメントは、すべての記事
3間でユーザBによってすべてのコメントを取得します。すべてのコメントを得るユーザーBは

に投票しました

私の最初の試みは、記事とコメントを別々のコレクションに入れ、コメントに投票したユーザーのリストを含めることです。これにより、クエリー1と2が簡単になります。そして3のために、私はユーザーによる投票のトラックを保持する投票コレクションを追加しました。

ユーザー投票データを複製するなどの明らかな欠点があります。クエリ1では、データベースに2回の呼び出しが行われます。より良いアプローチがありますか?

Article { 
    "user_id" 
} 

Comment { 
    "user_id", 
    "article_id", 
    [user_voted], 
} 

Vote { 
    "user_id", 
    "comment_id", 
} 

答えて

28
Article { 
    "_id" : "A", 
    "title" : "Hello World", 
    "user_id" : 12345, 
    "text" : 'My test article', 

    "comments" : [ 
    { 'text' : 'blah', 'user_id' : 654321, 'votes' : [987654]}, 
    { 'text' : 'foo', 'user_id' : 987654, 'votes' : [12345, 654321] }, 
    ... 
    ] 
} 

ここで基本的な前提は、私​​がArticleComments内部に入れ子になったことです。 VotesCommentにのみ適用されるため、それぞれがCommentの配列として保存されています。この場合、私はuser_idを保存しました。あなたは(などTIME_CREATED、)より多くの情報を保存したい場合は、オブジェクトの配列を投票することができます

... 'votes' : [ { user_id : 987654, ts : 78946513 } ] ... 

効率的にクエリを実行する方法:

  1. 条A、コメントを取得します条Aおよびコメントにつき投票の#
db.articles.find({ _id : 'A' }) 

これが取得するにすべて1つのクエリでコメントあたりの投票数をカウントするためにいくつかのクライアントサイドのロジックを行う必要があるかもしれませんが、これはかなり簡単です。

  1. は、効率的に文書内のコメントを検索することができますすべての記事
db.articles.ensureIndex({ "comments.user_id" : 1 }) 
db.articles.find({ "comments.user_id" : 987654 }) // returns all document fields 

インデックス全体でユーザBによってすべてのコメントを取得します。

現在のところ、サブアレイからの一致のみを抽出する方法はありません。このクエリは、実際にはそのユーザーがコメントを持つすべての記事を返します。これがデータの量が多すぎる場合は、トリミングを行うことができます。

db.articles.find({ "comments.user_id" : 987654 }, { "title" : 1, "comments.user_id" : 1 }) 
  1. はBが再び
    db.articles.ensureIndex({ "comments.votes" : 1 }) 
    db.articles.find({ "comments.votes" : 987654 }) 
    

に投票したすべてのコメントユーザーを取得し、これは記事だけでなく、すべてのコメントを返します。

ここではトレードオフがあります。記事を返すと、あまりにも多くのデータを取り戻すように見えるかもしれません。しかし、クエリ#3を作成するときに、ユーザーに表示する予定は何ですか?

のリストを取得するコメント「に投票しました」というコメント自体はあまり役に立ちません。もちろん、コメントは記事自体(または少なくともタイトルのみ)なしではあまり有用ではありません。

ほとんどの場合、クエリ#3はVotesからCommentsからArticlesへの結合になります。それが事実なら、なぜ始める記事を戻さないのですか?

+3

16MB /文書の制限はありますか? –

+0

1つのブログ投稿が16MBを超えることが心配な場合は、別のスキーマデザインを作成する必要があります。多くのブログは実際にはこれを別々のクエリとして提供しているため、実際には両方の部分に同時にアクセスすることはありません。これがあなたの心配であれば、別のスキーマを選択します。 –

+0

私はブログのために同様のデザインが必要です。私はモデレートのためにすべての記事から日付順に並べ替えてコメントを取得する必要があります。今、この結果も改ページされるべきです。私はまだこのアーキテクチャに固執すべきか、コメントセクションを別のコレクションに取り込むべきですか? –

関連する問題