2016-08-17 5 views
2

Мне нужно сделать запрос с индексом на mongodb, я покажу ниже пример минимального примера моего реального случая.

Я следующий сбор с протекающими данными:

devsrv(mongod-3.0.4) test> db.teste.find() 
{ 
    "_id": ObjectId("57b324c341aaa4b930ef3b92"), 
    "a": 1, 
    "b": 1 
} 
{ 
    "_id": ObjectId("57b324c941aaa4b930ef3b93"), 
    "a": 1, 
    "b": 2 
} 
{ 
    "_id": ObjectId("57b324cd41aaa4b930ef3b94"), 
    "a": 1, 
    "b": 3 
} 
{ 
    "_id": ObjectId("57b324d141aaa4b930ef3b95"), 
    "a": 1, 
    "b": 4 
} 
{ 
    "_id": ObjectId("57b324d541aaa4b930ef3b96"), 
    "a": 1, 
    "b": 5 
} 
{ 
    "_id": ObjectId("57b324da41aaa4b930ef3b97"), 
    "a": 1, 
    "b": 6 
} 
{ 
    "_id": ObjectId("57b324df41aaa4b930ef3b98"), 
    "a": 1, 
    "b": 7 
} 
{ 
    "_id": ObjectId("57b324e441aaa4b930ef3b99"), 
    "a": 1, 
    "b": 8 
} 
{ 
    "_id": ObjectId("57b324f341aaa4b930ef3b9a"), 
    "a": 1, 
    "b": "" 
} 
{ 
    "_id": ObjectId("57b324f641aaa4b930ef3b9b"), 
    "a": 1, 
    "b": " " 
} 
{ 
    "_id": ObjectId("57b324fc41aaa4b930ef3b9c"), 
    "a": 1, 
    "b": null 
} 
{ 
    "_id": ObjectId("57b3250341aaa4b930ef3b9d"), 
    "a": 1 
} 
{ 
    "_id": ObjectId("57b46ace41aaa4b930ef3b9e"), 
    "a": 2 
} 

И у меня есть следующие индексы:

devsrv(mongod-3.0.4) test> db.teste.getIndexes() 
[ 
    { 
    "v": 1, 
    "key": { 
     "_id": 1 
    }, 
    "name": "_id_", 
    "ns": "test.teste" 
    }, 
    { 
    "v": 1, 
    "key": { 
     "a": 1, 
     "b": 1 
    }, 
    "name": "a_1_b_1", 
    "ns": "test.teste" 
    }, 
    { 
    "v": 1, 
    "key": { 
     "b": 1 
    }, 
    "name": "b_1", 
    "ns": "test.teste" 
    } 
] 

И мне нужно сделать запрос равным образом:

devsrv(mongod-3.0.4) test> db.teste.find({$or:[{"b":null},{"b":""},{"b":" "},{"b":{$lt:3}}],"a":1}).explain("executionStats") 
{ 
    "queryPlanner": { 
    "plannerVersion": 1, 
    "namespace": "test.teste", 
    "indexFilterSet": false, 
    "parsedQuery": { 
     "$and": [ 
     { 
      "$or": [ 
      { 
       "b": { 
       "$eq": null 
       } 
      }, 
      { 
       "b": { 
       "$eq": "" 
       } 
      }, 
      { 
       "b": { 
       "$eq": " " 
       } 
      }, 
      { 
       "b": { 
       "$lt": 3 
       } 
      } 
      ] 
     }, 
     { 
      "a": { 
      "$eq": 1 
      } 
     } 
     ] 
    }, 
    "winningPlan": { 
     "stage": "FETCH", 
     "filter": { 
     "a": { 
      "$eq": 1 
     } 
     }, 
     "inputStage": { 
     "stage": "FETCH", 
     "filter": { 
      "$or": [ 
      { 
       "b": { 
       "$eq": null 
       } 
      }, 
      { 
       "b": { 
       "$eq": "" 
       } 
      }, 
      { 
       "b": { 
       "$eq": " " 
       } 
      }, 
      { 
       "b": { 
       "$lt": 3 
       } 
      } 
      ] 
     }, 
     "inputStage": { 
      "stage": "IXSCAN", 
      "keyPattern": { 
      "b": 1 
      }, 
      "indexName": "b_1", 
      "isMultiKey": false, 
      "direction": "forward", 
      "indexBounds": { 
      "b": [ 
       "[null, null]", 
       "[-inf.0, 3.0)", 
       "[\"\", \"\"]", 
       "[\" \", \" \"]" 
      ] 
      } 
     } 
     } 
    }, 
    "rejectedPlans": [ 
     { 
     "stage": "FETCH", 
     "filter": { 
      "$or": [ 
      { 
       "b": { 
       "$eq": null 
       } 
      }, 
      { 
       "b": { 
       "$eq": "" 
       } 
      }, 
      { 
       "b": { 
       "$eq": " " 
       } 
      }, 
      { 
       "b": { 
       "$lt": 3 
       } 
      } 
      ] 
     }, 
     "inputStage": { 
      "stage": "IXSCAN", 
      "keyPattern": { 
      "a": 1, 
      "b": 1 
      }, 
      "indexName": "a_1_b_1", 
      "isMultiKey": false, 
      "direction": "forward", 
      "indexBounds": { 
      "a": [ 
       "[1.0, 1.0]" 
      ], 
      "b": [ 
       "[MinKey, MaxKey]" 
      ] 
      } 
     } 
     } 
    ] 
    }, 
    "executionStats": { 
    "executionSuccess": true, 
    "nReturned": 6, 
    "executionTimeMillis": 0, 
    "totalKeysExamined": 8, 
    "totalDocsExamined": 14, 
    "executionStages": { 
     "stage": "FETCH", 
     "filter": { 
     "a": { 
      "$eq": 1 
     } 
     }, 
     "nReturned": 6, 
     "executionTimeMillisEstimate": 0, 
     "works": 10, 
     "advanced": 6, 
     "needTime": 2, 
     "needFetch": 0, 
     "saveState": 0, 
     "restoreState": 0, 
     "isEOF": 1, 
     "invalidates": 0, 
     "docsExamined": 7, 
     "alreadyHasObj": 7, 
     "inputStage": { 
     "stage": "FETCH", 
     "filter": { 
      "$or": [ 
      { 
       "b": { 
       "$eq": null 
       } 
      }, 
      { 
       "b": { 
       "$eq": "" 
       } 
      }, 
      { 
       "b": { 
       "$eq": " " 
       } 
      }, 
      { 
       "b": { 
       "$lt": 3 
       } 
      } 
      ] 
     }, 
     "nReturned": 7, 
     "executionTimeMillisEstimate": 0, 
     "works": 8, 
     "advanced": 7, 
     "needTime": 1, 
     "needFetch": 0, 
     "saveState": 0, 
     "restoreState": 0, 
     "isEOF": 1, 
     "invalidates": 0, 
     "docsExamined": 7, 
     "alreadyHasObj": 0, 
     "inputStage": { 
      "stage": "IXSCAN", 
      "nReturned": 7, 
      "executionTimeMillisEstimate": 0, 
      "works": 8, 
      "advanced": 7, 
      "needTime": 1, 
      "needFetch": 0, 
      "saveState": 0, 
      "restoreState": 0, 
      "isEOF": 1, 
      "invalidates": 0, 
      "keyPattern": { 
      "b": 1 
      }, 
      "indexName": "b_1", 
      "isMultiKey": false, 
      "direction": "forward", 
      "indexBounds": { 
      "b": [ 
       "[null, null]", 
       "[-inf.0, 3.0)", 
       "[\"\", \"\"]", 
       "[\" \", \" \"]" 
      ] 
      }, 
      "keysExamined": 8, 
      "dupsTested": 0, 
      "dupsDropped": 0, 
      "seenInvalidated": 0, 
      "matchTested": 0 
     } 
     } 
    } 
    }, 
    "serverInfo": { 
    "host": "devsrv", 
    "port": 27017, 
    "version": "3.0.4", 
    "gitVersion": "0481c958daeb2969800511e7475dc66986fa9ed5" 
    }, 
    "ok": 1 
} 

Но MongoDB не использует два индекса вместе.

+0

Кто-нибудь знает, скажите мне, как заставить монго использовать два индекса? –

ответ

0

Каждый $or термин представляет собой отдельный запрос, поэтому он помогает структурировать ваш запрос, чтобы каждый член выравнивался с индексом, который вы надеетесь использовать. В этом случае, что означает переход в a: 1 части внутри каждого термина $or:

db.teste.find({ 
    $or:[ 
    {a: 1, b: null}, 
    {a: 1, b: ""}, 
    {a: 1, b: " "}, 
    {a: 1, b: {$lt: 3}} 
    ]}).explain('executionStats') 

объяснения, вывод показывает, что a_1_b_1 используется для этого запроса.

Но вы можете упростить это немного больше, используя $in объединить первые три члена в одну:

db.teste.find({ 
    $or:[ 
    {a: 1, b: {$in: [null, "", " "]}}, 
    {a: 1, b: {$lt: 3}} 
    ]}).explain('executionStats') 

Это также может использовать индекс a_1_b_1.

+0

Я не использую дважды параметр a, в этом случае этот параметр является из динамического запроса –

0

Код

db.teste.explain("executionStats").find({a: 1, 
             $or:[{b: null}, 
               {b: ""}, 
               {b: " "}, 
               {b: {$lt:3}}] 
             }).hint({a: 1, b: 1}) 

Будьте осторожны с командой hint как оптимизатор запросов выбирает наиболее эффективный запрос путем измерения фактической производительности запроса с каждым подходящим индексом.

+0

очень хорошо это может помочь, спасибо! –

+0

@DimiAntoniVargas Это хорошая практика, чтобы принять ответы, которые решают вашу проблему :-) – BVengerov

Смежные вопросы