Query-Performance
MongoDB 不使用萬用字元嵌套數組索引
我有以下收藏:
{ _id: 12345, quizzes: [ { _id: 111111, done: true } ] }, { _id: 78910, quizzes: [ { _id: 22222, done: false } ] }
我想從測驗中選擇某個測驗所在的文件,
done
並希望確保它使用適當的索引。所以我使用以下查詢:Answer.find({ 'quizzes.0.done': true }).explain('queryPlanner');
返回:
queryPlanner: { plannerVersion: 1, namespace: 'iquiz.answers', indexFilterSet: false, parsedQuery: { 'quizzes.0.done': [Object] }, winningPlan: { stage: 'COLLSCAN', filter: [Object], direction: 'forward' }, rejectedPlans: [] }
從輸出中可以看出,該查詢未使用任何索引。我嘗試了以下索引,但沒有一個被使用:
{ quizzes.done: 1 } { quizzes.[$**].done: 1 } { quizzes: 1 }
唯一實際使用的 1:
{ quizzes.0.done: 1 }
但是,這並不實用,因為我可能會針對測驗數組中的任何測驗而不僅僅是第一個測驗。在我的情況下,索引是否有某種語法,或者這是 mongodb 的目前限制?謝謝!
當 MongoDB 索引數組或子文件數組中的欄位時,索引本質上是 value -> recordId 對的列表。
value 部分是實際的欄位值,不包含關於數組中值的索引的任何資訊。
查詢執行器的索引掃描將查詢值與索引值匹配,並返回需要獲取的記錄 ID 列表。
如果您有其他要求,例如 elemMatch 子句或要求值位於數組中的特定位置,則必須在索引掃描後檢查文件。
這意味著如果您使用索引
{"quizzes.done":1}
來匹配"quizzes.0.done": true
,則執行程序需要檢索包含至少 1 個已完成測驗的所有文件,並檢查每個文件以確定它是否是第一個索引。在這種情況下,收集掃描很可能更有效。您注意到索引
{"quizzes.0.done":1}
適用於該查詢,但這是因為查詢執行程序可以保證該索引在數組中的匹配位置,並確保沒有其他數組元素會匹配。我不確定如何
{ quizzes.[$**].done: 1 }
處理索引,但我懷疑它看起來不會有太大不同{ quizzes.done: 1 }