2011-08-09 8 views
6

ここでは取引があります。我々はMongoDBの中に、以下のデータスキーマを持っているとしましょう:埋め込みが答えではない場合、MongoDBの多対多関係をどう扱うか?

  • items:いくつかのデータを保持する大きな文書のコレクション(それが実際に何であるか絶対に無関係です)。
  • item_groupsitem_groups.itemsと呼ばれるitems._idというリストを含むドキュメントを含むコレクション。

したがって、これらの2つは多対多の関係で結ばれています。しかし、難しいことが1つあります。特定の理由からアイテムグループ内にアイテムを格納できないため、タイトルと同様に埋め込みは答えではありません。

私が本当に心配している質問は、特定のアイテムを含む特定のグループを見つけることです(つまり、コレクションごとに基準を設定しています)。実際には、見つけられた各グループ内のアイテムがどれくらいの基準を満たしているかも言わなければなりません(アイテムがないということはグループが見つからないことを意味します)。私はこの思い付いた

唯一の実行可能な解決策は、これまでの機能を減らすダミーとアプローチを削減/地図を使用することです:

function map() { 
    // imagine that item_criteria came from the scope. 
    // it's a mongodb query object. 
    item_criteria._id = {$in: this.items}; 
    var group_size = db.items.count(item_criteria); 
    // this group holds no relevant items, skip it 
    if (group_size == 0) return; 

    var key = this._id.str; 
    var value = {size: group_size, ...}; 

    emit(key, value); 
} 

function reduce (key, values) { 
    // since the map function emits each group just once, 
    // values will always be a list with length=1 
    return values[0]; 
} 

db.runCommand({ 
    mapreduce: item_groups, 
    map: map, 
    reduce: reduce, 
    query: item_groups_criteria, 
    scope: {item_criteria: item_criteria}, 
}); 

問題ラインは次のとおりです。

item_criteria._id = {$in: this.items}; 

何本かの.items.length == 5000以上?私のRDBMSの背景には、大声で叫ぶ:

SELECT ... FROM ... WHERE whatever_id IN (over 9000 comma-separated IDs) 

は間違いを行くには良い方法ではありません。

お時間をいただきありがとうございます。

私は最高の答えは「あなたは愚かだRDBMSスタイルで思考停止し、MongoDBの最新リリースから$ its_a_kind_of_magicSphereを使用する」のようなものことを願っています:)

+0

...のMongoDB及びその他の文書データベースが得意な何かであるということです - > http://www.mongodb.org/display/DOCS/データベース+参照#DatabaseReferences - Javascript%28mongoshell%29? – DrColossos

+0

私は、実際の埋め込みすなわち別のドキュメント内に1つのドキュメントを格納することについて話しています。例えばコメント= {ユーザー: 'DrColossos'、テキスト: 'あなたは何を話していますか?';質問= {x:13、y:42、コメント:[コメント]} –

+0

中間テーブルを使用して多対多リレーションシップを作成し、それをクエリすると、あなたの問題を解決することはありませんか? – Qqbt

答えて

1

なぜ反対を使用していません設計 ?

あなたはitemとitem_groupsを保存しています。あなたの最初のアイデアはitem_groupエントリ内の項目を格納する場合は、多分反対が

:-)悪い考えではない私に説明してみましょう:あなたは、それが属するグループを格納し、各項目における

を。 (あなたはNOSqlにあり、データの複製はOKです) たとえば、項目の項目にグループと呼ばれるリストを格納し、項目は次のようになります: {_id:.... 、名前:.... 、基:[たObjectId(...)のObjectId(...)のObjectId(...)]}

そしてマップのアイデアが低減は多くの電力を要する:

map = function() { 
    this.groups.forEach(function(groupKey) { 
     emit(groupKey, new Array(this)) 
    } 
} 


reduce = function(key,values) { 
    return Array.concat(values); 
} 


db.runCommand({ 
    mapreduce : items, 
    map : map, 
    reduce : reduce, 
    query : {_id : {$in : [...,....,.....] }}//put here you item ids 
}) 

いくつかのパラメータを追加することができます(たとえば、マップの出力を変更するためにファイナライズする)が、これはあなたを助けるかもしれません。もちろん

は、あなたがたが、いくつかのケースでは(item_groupsについては、この情報が存在しないDOE、または変更しない、またはそうでない場合は、それを持っている必要がある場合はitem_groupsの詳細を格納別のコレクションを持っている必要がありますあなたがそれの最新バージョンを持っていないことに気をつけてください)あなたはそれらをまったく必要としません!

これは、あなたの問題の解決方法を示唆していますか?

4

私は、データベーススキーマモデリングからドメイン/オブジェクトモデリングの分離に苦労していると思います。私もMongoDbを試してみるとこれと苦労しました。

セマンティクスと明確化のために、私は言葉Categories

Groupsを代用するつもりです基本的に、あなたの理論モデルは、各ItemCategoriesに属することができるという関係では「多くの多くの」であり、各Category多くの場合Itemsを所有することができます。

これが最良の文書データベース(のNoSQL)を実装する場合は特に、あなたのドメイン・オブジェクト・モデリングでは、ないDBスキーマで処理されます。 MongoDbスキーマでは、トップレベルのドキュメントモデルと埋め込みを組み合わせて、多対多の関係を「偽造」します。

埋め込みは、SQLの永続性のバックエンドから来る人々のために飲み込むのは難しいですが、それは答えの重要な部分です。あなたのCategory文書は、独自のいくつかのデータが含まれているなど


トップレベルの文書モデル

のでトリックは、それが一方向または双方向、浅いか深いあるかどうかを決定されます広範囲に番号Itemsで参照されていますが、それぞれItemの中に完全に埋め込むことは賢明ではないことに同意します。

代わりに、トップレベルの文書としての両方ItemCategoryオブジェクトを扱います。 MongoDbスキーマがそれぞれのテーブルを割り当てて、各ドキュメントが独自のObjectIdを持つようにしてください。

次のステップでは、それはすべてあなたがそれを使用するとどのようなあなたのスケーリングの野望があるかに依存する権利答えはありません...どこで、どのくらいの埋め込むことを決定することです...

は、意思決定を埋め込み

1.最低限のアイテム

、あなたのItemオブジェクトは、そのカテゴリのコレクションプロパティを持つ必要があります。少なくともこのコレクションにはCategoryごとにObjectIdが含まれている必要があります。

私の提案は、私は私のWebページ上のアイテムの束を一覧表示したい場合は、例えば

...このコレクション、Item最も頻繁にと対話するときに使用するデータに追加することですグリッドを表示し、それらの一部であるカテゴリの名前を表示します。Categoryについてすべてを知る必要はないことは明らかですが、ObjectIdのみが埋め込まれている場合は、その詳細を取得するために2番目のクエリが必要になります。

は、代わりに何を最も理にかなってはItemを引き戻すことは今別のクエリせずにそのカテゴリ名を表示できるように、ObjectIdと一緒にコレクション内のカテゴリーのNameプロパティを埋め込むことです。覚えておくべき

最大のものはCategoryそれはOOPやリレーショナルデータベースモデリングではありません...本当のCategoryドキュメントモデルと一致する必要はありません「を表す」というあなたのItemに埋め込まれたキー/値オブジェクトということです。あなたは一方通行を埋め込む残すことを選択し、あなたのCategory文書内の任意Itemの情報を持っていない...またはあなたは多くの項目データの収集を追加することを選択する場合があります逆に

2.カテゴリー

この方向で(ObjectId、またはObjectId + Name)...

上記のように、私は個人的に私は私のカテゴリのItem情報が必要な場合はおそらくよりも、私はそれはたくさん欲しい...埋め込まれた何も持っていない方に傾くだろう、名前だけではなく...トップレベルのドキュメントを深く埋め込むnt(Item)は意味をなさない。私は単純に、各コレクションがカテゴリのコレクションで自分のカテゴリのObjectIdを所有していたアイテムコレクションのデータベースを照会することに自信を持って辞任します。

Phew ...確かに混乱します。ポイントは、あなたいくつかのデータの重複を持つことになりますされ、あなた最高のパフォーマンスを得るために、あなたの使い方にあなたのモデルを微調整する必要があります。良いニュースは、あなたがDBReferencesについて話している「埋め込む」の話をするとそれが

関連する問題