2016-10-04 1 views
0

MongoDB 3.2에서 "커버 된 쿼리"테스트를하고 있는데, 동일한 필드에서만 $or 표현을 포함하는 쿼리를 처리하지 못한다는 사실을 발견했습니다. 그러나 동일한 쿼리에서 $in 표현식을 $or 표현식으로 대체하면 정상적으로 작동합니다.

내가 테스트에 사용 된 인덱스는 다음이었다

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

이것은 인덱스

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

적용 아니라는 $or 쿼리이며, 이것은 $in 쿼리입니다 그 입니다.

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

필드가 동일하고 투영법이 동일합니다. 그렇다면 색인에서 $or 검색어를 검색 할 수없는 이유는 무엇입니까?


$or 쿼리에 대한 explain() 출력 :

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

이이 $in 쿼리에 대한 explain() 출력 : 방식 때문에

{ 
     "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

$ 또는 연산자가 처리됩니다. 공식 MongoDB의 과정에서 video에 따르면

$ 또는 운영자 배열을 소요하고 배열 문서를 포함, 각 문서는 별도의 쿼리로 처리하고, $ 또는 운영자는 일치하는 모든 문서를 일치 배열 내부의 이러한 쿼리는 실제로 이 쿼리의 통합을 계산합니다. 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'을 추천하고 예제가 작동하지만 차이점이 무엇인지 알지 못합니다. 특히'$ or '쿼리와 내 쿼리 사이. 나에게 그것은 정확히 같은 쿼리 다. 나는 그것이 작동하지 않는 이유를 알고 싶다 (문서에 설명되어 있지 않기 때문에). 나는 이미 테스트에서 이것을 알고 있습니다 :) – Tom

+0

공식 mongodb 코스에서 [비디오] (https://www.youtube.com/watch?v=IE2d5DBjNsQ)를 이해하는 한, 차이점은 명령의 목적에 있습니다 . ** $ 또는 ** 연산자의 각 표현식은 별도의 쿼리로 처리되며 문서의 필드를 값 집합과 일치시키는 ** $ in **과 반대로 결과의 통합이 반환됩니다. –

+0

비디오의 마지막 순간에 실제로 문제가 해결되었습니다. 그들은 실제로 문서에서 언급해야합니다 :/그것을 찾아 주셔서 감사하고 그것을 연결. 이 정보를 포함하도록 답을 다시 쓸 수 있으면 기꺼이 "수락 함"으로 표시 할 것입니다. :) – Tom

관련 문제