我正在开发一个项目,要求我根据很多匹配(可能是100)来动态创建动态MongoDB查询。除了创建正确的索引之外,我想知道我是如何将匹配构建到管道中的。基于以下示例,这些示例中的一个是否与另一个示例的表现不同或更好?
我假设示例2会缩小结果集,但会更多调用?也许这就是示例1在幕后做的事情?
提前感谢您的帮助!
示例1
db.Test.aggregate(
[
{ $match: { item1: 'foo1', item2: 'foo2', item3: 'foo3' } }
])
VS
示例2
db.Test.aggregate(
[
{ $match: { item1: 'foo1' } },
{ $match: { item2: 'foo2' } },
{ $match: { item3: 'foo3' } }
])
我怀疑这个问题是否重要,但如果相关,我将使用C#驱动程序进行实施。
答案 0 :(得分:4)
我在MongoDB's documentation中找到了以下信息:
$match
+$match
合并当
$match
紧跟另一个$match
后,这两个阶段可以合并为一个$ match,将条件与$and
组合在一起。例如,管道包含以下序列:{ $match: { year: 2014 } }, { $match: { status: "A" } }
然后第二个$ match阶段可以合并到第一个$ match阶段并产生一个$ match阶段:
{ $match: { $and: [ { "year" : 2014 }, { "status" : "A" } ] } }
由此可以说,在raw中使用多个$match
与使用包含多个字段的单个$match
完全相同。
我不确定为什么优化引擎会在这里添加$and
运算符。根据{{3}},它没有必要,因此我认为可以忽略它。有人可以证实吗?
答案 1 :(得分:1)
我今天想知道同样的事情,偶然发现了罗曼的回答。虽然我想亲眼看到这个,但可以使用两个聚合的解释轻松完成;
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-pipelines还是一个组合$ match-pipeline,解析后的查询都将完全相同。