【问题标题】:MongoDB (3.0) Aggregation: Several matches vs One match with multiple itemsMongoDB(3.0)聚合:几个匹配与一个匹配多个项目
【发布时间】:2015-08-09 02:55:53
【问题描述】:

我正在开展一个项目,该项目需要我根据大量匹配(可能有 100 个)动态创建动态 MongoDB 查询。除了创建正确的索引之外,我想知道如何将匹配项构建到管道中是否重要。根据以下示例,其中一个示例的性能是否与另一个不同或更好?

我假设示例 2 会缩小结果集,但调用次数更多?也许这就是示例 1 在幕后所做的?

提前感谢您的帮助!

示例 1

db.Test.aggregate(
[     
   { $match: { item1: 'foo1', item2: 'foo2', item3: 'foo3' } }
])

示例 2

db.Test.aggregate(
[     
   { $match: { item1: 'foo1' } },
   { $match: { item2: 'foo2' } },
   { $match: { item3: 'foo3' } }
])

我怀疑这个问题是否重要,但如果相关,我将使用 C# 驱动程序来实现。

【问题讨论】:

  • 有趣的问题...你找到并回答了吗?
  • 我也很想知道!

标签: mongodb mongodb-query


【解决方案1】:

我在MongoDB's documentation找到了以下信息:

$match + $match 聚结

$match 紧跟在另一个$match 之后时,这两个阶段可以合并为一个$match,将条件与$and 结合起来。例如,管道包含以下序列:

{ $match: { year: 2014 } },
{ $match: { status: "A" } }

然后第二个 $match 阶段可以合并到第一个 $match 阶段并产生一个 $match 阶段:

{ $match: { $and: [ { "year" : 2014 }, { "status" : "A" } ] } }

由此我可以说,连续使用多个$match 与使用单个$match 和多个字段相同。

我不确定为什么优化引擎会在此处添加$and 运算符。根据this answer,它不应该是必要的,因此我认为可以忽略它。有人可以确认吗?

【讨论】:

  • 我还假设 $and 无论如何都是隐含的,所以它看起来确实没有必要,但它背后可能还有另一个原因
【解决方案2】:

我今天也在想同样的事情,偶然发现了 Romain 的答案。虽然我想亲眼看看这一点,但可以通过对两个聚合的解释轻松完成;

db.verpakking.explain().aggregate([
    { "$match": {type: "VERPAKT"} },
    { "$match": {ras: "CherryStar"} },
]);

这会导致以下输出:

{
  "waitedMS" : NumberLong(0),
  "stages" : [
    {
      "$cursor" : {
        "query" : {
          "$and" : [
            {
              "type" : "VERPAKT"
            },
            {
              "ras" : "CherryStar"
            }
          ]
        },
        "queryPlanner" : {
          "plannerVersion" : NumberInt(1),
          "namespace" : "denberk.verpakking",
          "indexFilterSet" : false,
          "parsedQuery" : {
            "$and" : [
              {
                "ras" : {
                  "$eq" : "CherryStar"
                }
              },
              {
                "type" : {
                  "$eq" : "VERPAKT"
                }
              }
            ]
          },
          "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
              "$and" : [
                {
                  "ras" : {
                    "$eq" : "CherryStar"
                  }
                },
                {
                  "type" : {
                    "$eq" : "VERPAKT"
                  }
                }
              ]
            },
            "direction" : "forward"
          },
          "rejectedPlans" : [

          ]
        }
      }
    }
  ],
  "ok" : NumberInt(1)
}

虽然

db.verpakking.explain().aggregate([
{ "$match": {type: "VERPAKT", ras: "CherryStar"} },
]);

输出结果:

{
  "waitedMS" : NumberLong(0),
  "stages" : [
    {
      "$cursor" : {
        "query" : {
          "type" : "VERPAKT",
          "ras" : "CherryStar"
        },
        "queryPlanner" : {
          "plannerVersion" : NumberInt(1),
          "namespace" : "denberk.verpakking",
          "indexFilterSet" : false,
          "parsedQuery" : {
            "$and" : [
              {
                "ras" : {
                  "$eq" : "CherryStar"
                }
              },
              {
                "type" : {
                  "$eq" : "VERPAKT"
                }
              }
            ]
          },
          "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
              "$and" : [
                {
                  "ras" : {
                    "$eq" : "CherryStar"
                  }
                },
                {
                  "type" : {
                    "$eq" : "VERPAKT"
                  }
                }
              ]
            },
            "direction" : "forward"
          },
          "rejectedPlans" : [

          ]
        }
      }
    }
  ],
  "ok" : NumberInt(1)
}

正如您所见,这完全一样,除了“查询”部分(这是正常的,因为我们的查询不同的)。这证明无论您使用两个单独的连续 $match-pipeline 还是一个组合的 $match-pipeline,解析后的查询都将完全相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 2020-06-24
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多