2016-10-04 112 views
0

我在MongoDB 3.2中做了幾個「覆蓋查詢」測試,注意到它不包含一個包含$or表達式的查詢(只在同一個字段上?)。但是,如果在同一個查詢中用$or表達式代替$in表達式,則它工作得很好。

我用於測試的指數如下:

db.test_collection.createIndex({ a: 1, b: 1, c: 1 }); 

這是$or查詢不是通過索引

db.test_collection.find({ 
    a: "string", 
    $or: [ 
     { b: true }, 
     { b: false }, 
    ], 
    c: "string" 
}, { a: 1, b: 1, c: 1, _id: 0 }); 

覆蓋,這是$in查詢is covered

db.test_collection.find({ 
    a: "string", 
    b: { $in: [ true, false ] }, 
    c: "string" 
}, { a: 1, b: 1, c: 1, _id: 0 }); 

字段是相同的,投影是相同的。那麼,爲什麼索引不能覆蓋$or查詢?


這是explain()輸出爲$or查詢:

{ 
     "queryPlanner" : { 
       "plannerVersion" : 1, 
       "namespace" : "test.test_collection", 
       "indexFilterSet" : false, 
       "parsedQuery" : { 
         "$and" : [ 
           { 
             "$or" : [ 
               { 
                 "b" : { 
                   "$eq" : true 
                 } 
               }, 
               { 
                 "b" : { 
                   "$eq" : false 
                 } 
               } 
             ] 
           }, 
           { 
             "a" : { 
               "$eq" : "string" 
             } 
           }, 
           { 
             "c" : { 
               "$eq" : "string" 
             } 
           } 
         ] 
       }, 
       "winningPlan" : { 
         "stage" : "PROJECTION", 
         "transformBy" : { 
           "a" : 1, 
           "b" : 1, 
           "c" : 1, 
           "_id" : 0 
         }, 
         "inputStage" : { 
           "stage" : "FETCH", 
           "filter" : { 
             "$or" : [ 
               { 
                 "b" : { 
                   "$eq" : true 
                 } 
               }, 
               { 
                 "b" : { 
                   "$eq" : false 
                 } 
               } 
             ] 
           }, 
           "inputStage" : { 
             "stage" : "IXSCAN", 
             "keyPattern" : { 
               "a" : 1, 
               "b" : 1, 
               "c" : 1 
             }, 
             "indexName" : "a_1_b_1_c_1", 
             "isMultiKey" : false, 
             "isUnique" : false, 
             "isSparse" : false, 
             "isPartial" : false, 
             "indexVersion" : 1, 
             "direction" : "forward", 
             "indexBounds" : { 
               "a" : [ 
                 "[\"string\", \"string\"]" 
               ], 
               "b" : [ 
                 "[MinKey, MaxKey]" 
               ], 
               "c" : [ 
                 "[\"string\", \"string\"]" 
               ] 
             } 
           } 
         } 
       }, 
       "rejectedPlans" : [ ] 
     }, 
     "executionStats" : { 
       "executionSuccess" : true, 
       "nReturned" : 2, 
       "executionTimeMillis" : 9, 
       "totalKeysExamined" : 2, 
       "totalDocsExamined" : 2, 
       "executionStages" : { 
         "stage" : "PROJECTION", 
         "nReturned" : 2, 
         "executionTimeMillisEstimate" : 10, 
         "works" : 3, 
         "advanced" : 2, 
         "needTime" : 0, 
         "needYield" : 0, 
         "saveState" : 0, 
         "restoreState" : 0, 
         "isEOF" : 1, 
         "invalidates" : 0, 
         "transformBy" : { 
           "a" : 1, 
           "b" : 1, 
           "c" : 1, 
           "_id" : 0 
         }, 
         "inputStage" : { 
           "stage" : "FETCH", 
           "filter" : { 
             "$or" : [ 
               { 
                 "b" : { 
                   "$eq" : true 
                 } 
               }, 
               { 
                 "b" : { 
                   "$eq" : false 
                 } 
               } 
             ] 
           }, 
           "nReturned" : 2, 
           "executionTimeMillisEstimate" : 10, 
           "works" : 3, 
           "advanced" : 2, 
           "needTime" : 0, 
           "needYield" : 0, 
           "saveState" : 0, 
           "restoreState" : 0, 
           "isEOF" : 1, 
           "invalidates" : 0, 
           "docsExamined" : 2, 
           "alreadyHasObj" : 0, 
           "inputStage" : { 
             "stage" : "IXSCAN", 
             "nReturned" : 2, 
             "executionTimeMillisEstimate" : 10, 
             "works" : 3, 
             "advanced" : 2, 
             "needTime" : 0, 
             "needYield" : 0, 
             "saveState" : 0, 
             "restoreState" : 0, 
             "isEOF" : 1, 
             "invalidates" : 0, 
             "keyPattern" : { 
               "a" : 1, 
               "b" : 1, 
               "c" : 1 
             }, 
             "indexName" : "a_1_b_1_c_1", 
             "isMultiKey" : false, 
             "isUnique" : false, 
             "isSparse" : false, 
             "isPartial" : false, 
             "indexVersion" : 1, 
             "direction" : "forward", 
             "indexBounds" : { 
               "a" : [ 
                 "[\"string\", \"string\"]" 
               ], 
               "b" : [ 
                 "[MinKey, MaxKey]" 
               ], 
               "c" : [ 
                 "[\"string\", \"string\"]" 
               ] 
             }, 
             "keysExamined" : 2, 
             "dupsTested" : 0, 
             "dupsDropped" : 0, 
             "seenInvalidated" : 0 
           } 
         } 
       } 
     }, 
     "serverInfo" : { 
       "host" : "VM-TOMLIN-HP", 
       "port" : 27017, 
       "version" : "3.2.6", 
       "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" 
     }, 
     "ok" : 1 
} 

,這是explain()輸出爲$in查詢:由於的方式

{ 
     "queryPlanner" : { 
       "plannerVersion" : 1, 
       "namespace" : "test.test_collection", 
       "indexFilterSet" : false, 
       "parsedQuery" : { 
         "$and" : [ 
           { 
             "a" : { 
               "$eq" : "string" 
             } 
           }, 
           { 
             "c" : { 
               "$eq" : "string" 
             } 
           }, 
           { 
             "b" : { 
               "$in" : [ 
                 false, 
                 true 
               ] 
             } 
           } 
         ] 
       }, 
       "winningPlan" : { 
         "stage" : "PROJECTION", 
         "transformBy" : { 
           "a" : 1, 
           "b" : 1, 
           "c" : 1, 
           "_id" : 0 
         }, 
         "inputStage" : { 
           "stage" : "IXSCAN", 
           "keyPattern" : { 
             "a" : 1, 
             "b" : 1, 
             "c" : 1 
           }, 
           "indexName" : "a_1_b_1_c_1", 
           "isMultiKey" : false, 
           "isUnique" : false, 
           "isSparse" : false, 
           "isPartial" : false, 
           "indexVersion" : 1, 
           "direction" : "forward", 
           "indexBounds" : { 
             "a" : [ 
               "[\"string\", \"string\"]" 
             ], 
             "b" : [ 
               "[false, false]", 
               "[true, true]" 
             ], 
             "c" : [ 
               "[\"string\", \"string\"]" 
             ] 
           } 
         } 
       }, 
       "rejectedPlans" : [ ] 
     }, 
     "executionStats" : { 
       "executionSuccess" : true, 
       "nReturned" : 2, 
       "executionTimeMillis" : 0, 
       "totalKeysExamined" : 2, 
       "totalDocsExamined" : 0, 
       "executionStages" : { 
         "stage" : "PROJECTION", 
         "nReturned" : 2, 
         "executionTimeMillisEstimate" : 0, 
         "works" : 3, 
         "advanced" : 2, 
         "needTime" : 0, 
         "needYield" : 0, 
         "saveState" : 0, 
         "restoreState" : 0, 
         "isEOF" : 1, 
         "invalidates" : 0, 
         "transformBy" : { 
           "a" : 1, 
           "b" : 1, 
           "c" : 1, 
           "_id" : 0 
         }, 
         "inputStage" : { 
           "stage" : "IXSCAN", 
           "nReturned" : 2, 
           "executionTimeMillisEstimate" : 0, 
           "works" : 3, 
           "advanced" : 2, 
           "needTime" : 0, 
           "needYield" : 0, 
           "saveState" : 0, 
           "restoreState" : 0, 
           "isEOF" : 1, 
           "invalidates" : 0, 
           "keyPattern" : { 
             "a" : 1, 
             "b" : 1, 
             "c" : 1 
           }, 
           "indexName" : "a_1_b_1_c_1", 
           "isMultiKey" : false, 
           "isUnique" : false, 
           "isSparse" : false, 
           "isPartial" : false, 
           "indexVersion" : 1, 
           "direction" : "forward", 
           "indexBounds" : { 
             "a" : [ 
               "[\"string\", \"string\"]" 
             ], 
             "b" : [ 
               "[false, false]", 
               "[true, true]" 
             ], 
             "c" : [ 
               "[\"string\", \"string\"]" 
             ] 
           }, 
           "keysExamined" : 2, 
           "dupsTested" : 0, 
           "dupsDropped" : 0, 
           "seenInvalidated" : 0 
         } 
       } 
     }, 
     "serverInfo" : { 
       "host" : "VM-TOMLIN-HP", 
       "port" : 27017, 
       "version" : "3.2.6", 
       "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" 
     }, 
     "ok" : 1 
} 
+0

您使用的是什麼MongoDB版本?另外,你可以發佈兩個查詢的'explain()'結果嗎? –

+0

@KevinAdistambha我正在使用3.2.6。在這個問題中增加了這個以及'explain()'輸出。 – Tom

回答

1

$或處理運算符。按照video從官方MongoDB的過程:

的$或運營商需要一個數組,數組包含的文件,每個 文件被視爲一個單獨的查詢和$或操作任何匹配任何文件匹配 這些查詢在數組內,所以它實際上計算這些查詢的聯合。

此外,作爲documentation狀態:

MongoDB的使用索引來評估一個$或表達,所有的 條款在$或表達必須通過索引來支持。 否則,MongoDB將執行收集掃描。

db.test_collection.find({ 
    $or: [ 
     { a: "string", b: true, c: "string"}, 
     { a: "string", b: false, c: "string" }, 
    ], 
}, { a: 1, b: 1, c: 1, _id: 0 }); 

此外,文件直接recommends使用$在操作來檢查同一領域的平等:

,如果你重寫了查詢,像這樣給定的指標將用於。

+0

當然,它建議'$ in',並且你的例子確實有效,但我沒有得到區別。特別是在你的'$或'查詢和我的。對我來說,這些都是完全相同的查詢。我想知道爲什麼它不起作用(因爲這不在文檔中描述),而不僅僅是它沒有。我已經知道從測試:) – Tom

+0

據我瞭解官方mongodb課程的[視頻](https://www.youtube.com/watch?v=IE2d5DBjNsQ),區別在於命令的目的。 ** $或**運算符中的每個表達式都被視爲一個單獨的查詢,並返回其結果的聯合,而不是**中的** $,它只是將文檔中的某個字段與一組值相匹配。 –

+0

視頻的最後一分鐘實際上已經清理了一些東西。他們應該在文檔中提及:/感謝您找到並鏈接它。如果您可以重寫您的答案以包含此信息,我會很樂意將其標記爲「已接受」:) – Tom

相關問題