12

お客様のMongoDBの見積もりを進めています。ent要件ごとに、名前と値のペアのエンティティ変数セットに関連付ける必要があります。

db.ent.insert({'a':5775, 'b':'b1'})
db.ent.insert({'c':'its a c', 'b':'b2'})
db.ent.insert({'a':7557, 'c':'its a c'})

この後ent、フィールドの存在を集中的にクエリする必要があります。

db.ent.find({'a':{$exists:true}})
db.ent.find({'c':{$exists:false}})

MongoDBドキュメントごと:

$exists は、インデックスを使用してもあまり効率的ではありません。すべてのインデックス付きの値を効果的にスキャンする必要があるため、 {$exists:true} を使用します。

そこの専門家は、さまざまな名前と値のペアをすばやく処理するためのより効率的な方法を (パラダイムをシフトしても) 提供できますか?

4

4 に答える 4

9

次のようにスキーマを再設計できます。

{
  pairs:[
  {k: "a", v: 5775},
  {k: "b", v: "b1"},
  ]
}

次に、キーのインデックスを作成します。

db.people.ensureIndex({"pairs.k" : 1})

この後、完全一致で検索できるようになります。

db.ent.find({'pairs.k':"a"})

@WesFreeman によって提案されたスパース インデックスと現在のスキーマを使用する場合は、検索する各キーにインデックスを作成する必要があります。キーが静的でない場合、書き込みパフォーマンスに影響するか、受け入れられない可能性があります。

于 2012-01-25T21:24:00.087 に答える
2

インデックス可能なクエリになるようにスキーマを再設計するだけです。あなたのユースケースは、 MongoDB The Definitive Guideに記載されている最初のアプリケーション例に似ています。

result.aキーをインデックス可能な場所に保存するだけの便利さが必要な場合。

既存の代わりに:

db.ent.insert({a:5775, b:'b1'})

行う

db.ent.insert({a:5775, b:'b1', index: ['a', 'b']})

次に、インデックス可能なクエリです。

db.end.find({index: "a"}).explain()
{
    "cursor" : "BtreeCursor index_1",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 1,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : {
        "index" : [
            [
                "a",
                "a"
            ]
        ]
    }
}

または、値でもクエリを実行する可能性がある場合:

db.ent.insert({
    a:5775, 
    b:'b1', 
    index: [
        {name: 'a', value: 5775}, 
        {name: 'b', value: 'b1'}
    ]
})

これもインデックス可能なクエリです。

db.end.find({"index.name": "a"}).explain()
{
    "cursor" : "BtreeCursor index.name_",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 1,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : {
        "index.name" : [
            [
                "a",
                "a"
            ]
        ]
    }
}
于 2012-01-26T09:23:08.513 に答える
1

各フィールドにインデックスが必要ですが、スパースインデックスがこれに対する答えだと思います。http://www.mongodb.org/display/DOCS/Indexes#Indexes-SparseIndexes

スパース インデックスは $exists:true クエリに役立ちます。

それでも、フィールドが本当にまばらでない場合 (ほとんどが設定されていることを意味します)、それほど役に立ちません。

更新私は間違っていると思います。$exists がスパース インデックスを使用しないという未解決の問題 ( https://jira.mongodb.org/browse/SERVER-4187 ) がまだあるようです。ただし、スパース インデックスを適切に使用しているように見える、find と sort を使用して次のようなことを行うことができます。

db.ent.find({}).sort({a:1});

例の値を使用して、違いの完全なデモを次に示します。

> db.ent.insert({'a':5775, 'b':'b1'})
> db.ent.insert({'c':'its a c', 'b':'b2'})
> db.ent.insert({'a':7557, 'c':'its a c'})
> db.ent.ensureIndex({a:1},{sparse:true});

find({}).sort({a:1})インデックス (BtreeCursor)を使用することに注意してください。

> db.ent.find({}).sort({a:1}).explain();
{
"cursor" : "BtreeCursor a_1",
"nscanned" : 2,
"nscannedObjects" : 2,
"n" : 2,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
    "a" : [
        [
            {
                "$minElement" : 1
            },
            {
                "$maxElement" : 1
            }
        ]
    ]
}
}

そしてfind({a:{$exists:true}})、フルスキャンを実行します:

> db.ent.find({a:{$exists:true}}).explain();
{
"cursor" : "BasicCursor",
"nscanned" : 3,
"nscannedObjects" : 3,
"n" : 2,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {

}
}

.hint({a:1}) を使用して、インデックスを強制的に使用することもできるようです。

> db.ent.find().hint({a:1}).explain();
{
"cursor" : "BtreeCursor a_1",
"nscanned" : 2,
"nscannedObjects" : 2,
"n" : 2,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
    "a" : [
        [
            {
                "$minElement" : 1
            },
            {
                "$maxElement" : 1
            }
        ]
    ]
}
}
于 2012-01-25T21:02:57.007 に答える