MongoDB $或索引为

时间:2016-08-17 17:52:27

标签: mongodb mongodb-query

我需要在mongodb上使用indice进行查询,我将在下面显示我的真实案例的最小案例。

我收集了流动数据:

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并没有将这两个索引放在一起。

2 个答案:

答案 0 :(得分:0)

代码是

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

小心hint命令,因为查询优化器通过使用每个合适的索引测量查询的实际性能来选择最有效的查询。

答案 1 :(得分: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索引。