Query-Performance

MongoDB 不使用萬用字元嵌套數組索引

  • August 20, 2020

我有以下收藏:

{
  _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 }

引用自:https://dba.stackexchange.com/questions/274020