MongoDB(3.0)聚合:多个匹配与一个匹配多个项目

Mat*_*att 6 mongodb mongodb-query

我正在开发一个项目,要求我基于很多匹配(可能是100)来动态创建动态MongoDB查询.除了创建正确的索引之外,我想知道我是如何将匹配构建到管道中的.基于以下示例,这些示例中的一个是否与另一个示例的表现不同或更好?

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

在此先感谢您的帮助!

例1

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

VS

例2

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

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

Rom*_*n G 5

我在MongoDB的文档中找到了以下信息:

$match+ $match合并

$match紧随另一个紧接着$match的两个阶段时,这两个阶段可以合并为一个$ match,将条件与组合在一起$and。例如,管道包含以下序列:

{ $match: { year: 2014 } },
{ $match: { status: "A" } }
Run Code Online (Sandbox Code Playgroud)

然后,第二个$ match阶段可以合并到第一个$ match阶段,并导致一个$ match阶段:

{ $match: { $and: [ { "year" : 2014 }, { "status" : "A" } ] } }
Run Code Online (Sandbox Code Playgroud)

由此我可以说,$match在原始数据中使用多个绝对等同于$match在多个字段中使用单个。

但是我不确定为什么优化引擎会$and在此处添加运算符。根据这个答案,它不是必须的,因此我认为可以忽略不计。有人可以确认吗?


Ste*_*efK 5

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

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

这会产生以下输出:

{
  "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)
}
Run Code Online (Sandbox Code Playgroud)

尽管

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

输出结果:

{
  "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)
}
Run Code Online (Sandbox Code Playgroud)

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