0

問題

「全体」として定義されたドキュメントを、全体とその部分の両方がクエリ可能な「部分」の小さな固定コレクションにモデル化する必要があります。

スライスしたパイは、私が必要とするモデルの良い例です。ドメインについてさらに説明します。

  • pie:slice には 1:多 (1-10) の関係があります。各スライスは 1 つのパイにのみ属し、各パイには 1 ~ 10 のスライスがあります。
  • この例では、パイは作成時にスライスされ、スライスの数は変わらないと仮定します。
  • パイは常にそのスライスで照会されます。逆は必ずしも真ではありませんが、クエリされたスライスは円に関するメタデータにアクセスする必要があります
  • 例として、"weight" がスライスの唯一のプロパティであるとします。すべてのスライスで共有されるメタデータは、各スライスのメタデータよりもはるかに大きくなります。すべてのスライスのパン、フィリング、クラスト、キッチンなどは同じです。すべてのデータを各スライスに複製する必要がないことが理想的です
  • スライスとパイの両方が効率的にクエリ可能であり、パイ全体の属性またはスライスの属性によってソート可能でなければなりません。例:
    • ちょうど 2 切れ​​のパイをすべて見つける
    • スライスの重さが 10 オンスを超えるすべてのパイを見つける
    • タイプが「cherry」のすべてのスライスを検索します
    • すべてのパイで最も重い 5 つのスライスを見つける

質問:

上記のポイントを考えると、どのようにして 1 つのモデルpieslices効率的にクエリ可能にする (そして可能であれば効率的に格納する) ことができるでしょうか?

これが明らかな場合は、回答してください。これまでに試した 2 つのアプローチと、どちらも満足できない理由について説明します。


私が試したこと:

1.埋め込み

全体の中に部分を埋め込むのは当然の選択のように思えた

Pie {
  type: String, // `type` and other shared attrs are defined on Pie
  slices: [{
    _id: ObjectId
    weight: Number
  }]
}

これにより、タイプ、重量、スライスの重量でパイをクエリできaggregate、 、unzip、およびを介して個々のチェリー パイ スライスをクエリできますproject

問題は、個々のスライスをソートしてクエリする方法にあります。たとえば、すべてのパイから 5 つの最も重いスライスを取得する必要があるとします (上記の問題で説明したように)。これは集計で可能ですが、方法がわかりません。


2. コレクションを分ける

最初のスキーマをあきらめた後、参照 ID で結合された 2 つの個別のコレクションを使用することに戻りました。

Pie {
  type: String // `type` and other shared attrs are defined on Pie ...
}

Slice {
  pie_id: ObjectId,
  type: String, // ... and duplicated to all slices
  weight: Number
}

これでクエリの問題は解決しますが、さらにいくつかの問題が発生します。ここでtypeは複製されているだけです。私の実際のアプリケーションでは、これははるかに悪く、私のアナログSliceはおそらく 90% 重複データです。

もう 1 つの問題は、パイを照会するたびに、すべてのスライスを再度照会する必要があることです。さらに、パイの作成はアトミック操作ではなく、個別の挿入のバッチです。

4

3 に答える 3

0

これをご覧になりましたか: http://docs.mongodb.org/manual/tutorial/model-tree-structures/ 特に、「子参照を含むモデル ツリー構造」はまさにあなたが探しているもののようです。スライス ドキュメントの特定のスライスに最も固有のデータ (スライスの重みなど) のみを格納し、それ以外はすべて Pie ドキュメントに格納できます。

于 2013-02-06T22:28:45.880 に答える
0

私が行った答えは、おそらく唯一の答えでも最良の答えでもありませんが、関係の両側でデータを非正規化することでした。

基本的に、はドキュメント内slices完全に埋め込まれ、スライスは複製されたメタデータを備えた独自のコレクションに存在します。このようにして、二次クエリを必要とせずに、パイとそのスライスを個別にクエリできます。 piepie

2 方向の複製ストレージは効率的ですか? おそらくそうではありませんが、ここでもストレージは問題ではありません。

これにより、ドキュメントの更新がより複雑になり、複数の操作が行われますか? はい、しかし、更新は読み取りよりもはるかに少なく発生します。この場合、読み取りははるかに重要です。

于 2013-09-16T01:14:13.137 に答える
0

次のような構造を使用できますか。

{
    "_id" : ObjectId("5112d747819e326e6c37e1e3"),
    "pie" : {
        "type" : "cherry",
        "weight" : 500,
        "slices" : [
            {
                "slice_id" : ObjectId("5112d747819e326e6c37e1e1"),
                "type" : "square",
                "weight" : 75
            },
            {
                "slice_id" : ObjectId("5112d747819e326e6c37e1e2"),
                "type" : "triangle",
                "weight" : 75
            }
        ]
    }
}

次に、次のように $unwind と $sort を使用できます。

db.q14735834.aggregate({$unwind: "$pie.slices"}, {$sort: {"pie.slices.weight":-1}}, {$limit:10})

さらに、$group とその他の集計フレームワーク演算子を組み合わせてデータを操作します。

[Alptigin Jalayr] で参照されているチュートリアルとは別に、集約フレームワークのドキュメントが役立つ場合があります: http://docs.mongodb.org/manual/applications/aggregation/

于 2013-02-06T22:54:50.630 に答える