具有匹配(2个字段)和排序(匹配中的1个字段)的mongo聚合查询的性能

时间:2020-06-06 17:17:38

标签: mongodb

我在mongo数据库中有很多记录。并且我尝试执行聚合查询。 我的查询是:

db.collection.aggregate([
 {
    "$match": {
       "$or": [
          {
             "field1": {
                "$regex": ".*\\Q...\\E.*", // where ... - any text
                "$options": "i"
             }
          },
          {
             "field2": {
                "$regex": ".*\\Q...\\E.*", // where ... - any text
                "$options": "i"
             }
          }
       ]
    }
 },
 {
    "$sort": {
       "field1": 1
    }
 },
 // another operations, such as limit, skip
])

但是我有一个问题,这种匹配非常慢。 我有以下索引:

{
   "field1": 1
}


{
   "field2": 1
}

{
   "field1": 1,
   "field2": 1
}

但是当我删除field2的匹配项时,该查询的运行速度更快

在我所有的情况下,正则表达式都与field1和field2匹配,因此我尝试在应用程序级别将此字段作为field1AndField2组合到一个字段中,并为此字段添加索引。同样,它的运行速度很慢,但是当我在排序中使用该字段时,查询的工作速度更快,但是我无法在排序中使用此字段,这会影响最终结果。

您对此有任何想法吗?

更新07.06

添加了对具有复合索引的聚合查询的说明:

{
  "stages": [
    {
      "$cursor": {
        "query": {
          "$or": [
            ... // or with two fields
          ]
        },
        "sort": {
          ... // sort with field1
        },
        "queryPlanner": {
          ...
          "parsedQuery": {
            "$or": [
              ... // or with two fields
            ]
          },
          "winningPlan": {
            "stage": "SUBPLAN",
            "inputStage": {
              "stage": "FETCH",
              "filter": {
                "$or": [
                  ... // or with two fields
                ]
              },
              "inputStage": {
                "stage": "IXSCAN",
                "keyPattern": {
                  "field1": 1,
                  "field2": 1
                },
                "indexName": "...", // index name
                "multiKeyPaths": {
                  "field1": [],
                  "field2": []
                },
                ...
                "indexBounds": {
                  "field1": [
                    "[MinKey, MaxKey]"
                  ],
                  "field2": [
                    "[MinKey, MaxKey]"
                  ]
                }
              }
            }
          },
          "rejectedPlans": []
        }
      }
    }
  ]
}

1 个答案:

答案 0 :(得分:0)

您尝试通过更改$ or和$ match位置来尝试吗?

db.collection.aggregate([
     {
      "$or": [
        {
          "$match" : {
            "field1": {
              "$regex": ".*\\Q...\\E.*", // where ... - any text
              "$options": "i"
            }
          }
        },
        {
          "$match": {
            "field2": {
              "$regex": ".*\\Q...\\E.*", // where ... - any text
              "$options": "i"
            }
          }
        }
      ]
     },
     {
        "$sort": {
           "field1": 1
        }
     },
     // another operation, such as limit, skip
    ])