8

ネストされたセット (コメントのツリーなど) を MongoDB に格納するためのベスト プラクティスは何ですか?

つまり、すべてのコメントには、親コメントと子コメント (回答) を含めることができます。

次のように保存します。

{
   title: "Hello",
   body: "Please comment me!",
   comments: [
        {
            author: "Peter",
            text: "Hi there",
            answers: [
                  {
                      author: "Peter",
                      text: "Hi there",
                      answers: [
                                 { author: "Ivan", text: "Hi there" },
                                 { author: "Nicholas", text: "Hi there" }
                      ]
                  },
                  { author: "Ivan", text: "Hi there" },
                  { author: "Nicholas", text: "Hi there" },
            ]
        },
        { author: "Ivan", text: "Hi there" },
        { author: "Nicholas", text: "Hi there" },
   ]
}

たとえば、map/reduce なしでは「Peter がコメントしたすべての投稿」を求めることはできないため、クールではありません。

4

2 に答える 2

4

完璧な解決策はないと思います-アプリにとってより重要な操作によって異なります。たとえば、Silicon Alley Insider はコメントを MongoDB にネストして保存していると思います。それはあなたが言及するクエリを難しくします。

1 つのオプションは、配列内のすべてのコメント投稿者のリストを投稿の最上位に格納することです。それを非正規化データと考えてください。次に、特定のコメント投稿者を含むすべての投稿を簡単に見つけることができます。次にドリルダウンするには、map/reduce または db.eval() を使用して、ネストされた投稿情報を取得します。

もう 1 つの注意点 - 単一のドキュメントを扱っている場合、db.eval() はおそらく map/reduce より軽量です。$where もオプションですが、遅くなる可能性があるため、上記の追加の「コメンターのリスト」が好きです-その配列にインデックスを付けることも簡単ではありません(ドキュメントの「マルチキー」を参照)。

参照: http://groups.google.com/group/mongodb-user/browse_thread/thread/df8250573c91f75a/e880d9c57e343b52?lnk=gst&q=trees#e880d9c57e343b52

于 2009-12-06T15:01:39.590 に答える
2

dmの投稿からのリンクで、Dwight Merrimanは、パスキーの使用と正規表現の一致の実行について言及しています。

{
  path : "a.b.c.d.e.f"
}

これを行う別の方法は、配列を使用することです

{
  path : ["a", "b", "c", "d", "e", "f"]
}

db.test.ensureIndex({path: 1})

それはそれをかなり速くするはずです。

各ノードが単一のパスにしか存在できない場合は、リスト内のどこにあるかを心配する必要はありません。

db.test.find({path: "a"})

「a」のすべての子を見つける

パス名の代わりに、おそらくノードの_idを使用します。

アップデート

  • 注意すべきことの1つは、インデックスには1つの配列しか含めることができないということです。
  • クエリでexplainを使用するように注意してください

    db.test.find({path:{$ in:["a"、 "b"]})

あなたにあげる

 db.test.find({path: {$in: ["a", "b"]}}).explain()
{
        "cursor" : "BtreeCursor path_1 multi",
        "nscanned" : 2,
        "nscannedObjects" : 2,
        "n" : 1,
        "millis" : 0,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : true,
        "indexOnly" : false,
        "indexBounds" : {
                "path" : [
                        [
                                "a",
                                "a"
                        ],
                        [
                                "b",
                                "b"
                        ]
                ]
        }
}

しかし

 db.test.find({path: {$all: ["a", "b"]}}).explain()
{
        "cursor" : "BtreeCursor path_1",
        "nscanned" : 1,
        "nscannedObjects" : 1,
        "n" : 1,
        "millis" : 0,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : true,
        "indexOnly" : false,
        "indexBounds" : {
                "path" : [
                        [
                                "a",
                                "a"
                        ]
                ]
        }
}

最初の要素のみを使用してから、一致するすべての結果をスキャンしてbを探します。
aがルート要素であるか、ほとんどのレコードに含まれている場合は、効率的なインデックスクエリの代わりに、レコードのほぼ完全なスキャンを実行します。

于 2010-09-14T16:27:09.490 に答える