【问题标题】:Performance for mongo aggregation query with match (2 fields) and sort (1 fields from matching)具有匹配(2 个字段)和排序(匹配 1 个字段)的 mongo 聚合查询的性能
【发布时间】:2020-06-06 17:17:38
【问题描述】:

我在 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 的匹配项时,这个查询会更快

在我的所有情况下,字段 1 和字段 2 的正则表达式匹配相同,因此我尝试在应用程序级别将此字段合并为一个字段作为字段 1AndField2 并为该字段添加索引。这也很慢,但是当我在排序中使用此字段时,查询会更快,但我不能在排序中使用此字段,它会影响最终结果。

你对这个问题有什么想法吗?

更新 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": []
        }
      }
    }
  ]
}

【问题讨论】:

  • explain() 告诉您什么,例如:aggregate([ your pipeline ], {explain:true}) 如果您在使用 IXSCAN 时没有看到 OR 的 2 个输入阶段,则说明发生了其他事情。
  • @BuzzMoschetti 感谢您的关注。我用附加信息更新了我的问题,其中包含有关使用 field1 和 field2 的复合索引的聚合查询的说明。如果您想了解更多信息,请通知我。

标签: mongodb


【解决方案1】:

你尝试过改变 $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
    ])

【讨论】:

  • 感谢您的建议。但这会导致错误:无法识别的管道阶段名称'$or'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-10
  • 1970-01-01
  • 1970-01-01
  • 2015-01-31
  • 2023-01-22
  • 1970-01-01
相关资源
最近更新 更多