フィールド配列の a の値のみをクエリしている場合、両方のインデックスがある意味で、クエリのパフォーマンスを向上させるのに役立つことは間違いありません。
ただし、次の 3 つのクエリを見てください。
> db.zaid.save({field : [{a: 1}, {b: 2}, {c: 3}] });
> db.zaid.ensureIndex({field:1});
> db.zaid.ensureIndex({"field.a":1});
#Query 1
> db.zaid.find({"field.a":1})
{ "_id" : ObjectId("50b4be3403634cff61158dd0"), "field" : [ { "a" : 1 }, { "b" : 2 }, { "c" : 3 } ] }
> db.zaid.find({"field.a":1}).explain();
{
"cursor" : "BtreeCursor field.a_1",
"nscanned" : 1,
"nscannedObjects" : 1,
"n" : 1,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"field.a" : [
[
1,
1
]
]
}
}
#Query 2
> db.zaid.find({"field.b":1}).explain();
{
"cursor" : "BasicCursor",
"nscanned" : 1,
"nscannedObjects" : 1,
"n" : 0,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
#Query 3
> db.zaid.find({"field":{b:1}}).explain();
{
"cursor" : "BtreeCursor field_1",
"nscanned" : 0,
"nscannedObjects" : 0,
"n" : 0,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"field" : [
[
{
"b" : 1
},
{
"b" : 1
}
]
]
}
}
配列にインデックスを付けたにもかかわらず、2 番目のクエリにはインデックスがありませんが、3 番目のクエリにはインデックスがあることに注意してください。データのクエリ方法に基づいてインデックスを選択することは、インデックス自体が必要なものかどうかを検討することと同じくらい重要です。Mongo では、注意を怠ると、インデックスの構造がクエリのパフォーマンスに大きな違いをもたらす可能性があります。それがあなたの最初の質問を説明していると思います。
2 番目の質問はもう少しオープンエンドですが、答えはデータのクエリ方法にあると思います。「fields.a」の値の照合のみに関心がある場合は、後で必要になる可能性のある他のインデックス用にメモリに空きを確保する必要があります。ただし、配列内のこれらの項目のいずれかに対して同じようにクエリを実行する可能性があり、配列が無限に大きくなることはないと合理的に確信している場合 (時間の経過とともにバインドされていないサイズまで大きくなる可能性のある配列にインデックスを付けないでください。インデックス配列が BSON で 1024 バイトに達すると、ドキュメントにインデックスを付けることができなくなります)。その場合は、配列全体にインデックスを付ける必要があります。この例としては、ユーザーの手札の各カードを説明する配列を含む、トランプの手札のドキュメントが考えられます。