【发布时间】:2020-06-14 01:08:54
【问题描述】:
我在下面写了聚合,它在集合中展开一个数组,然后检查每个展开的文档是否与给定对象 id 数组中的任何元素匹配。投影时,生成的集合通过条件进一步过滤。
db.collectionName.aggregate([
{ $unwind: {
path: "$field5",
preserveNullAndEmptyArrays: true
}
},
{ $match: { field5: { $in:
[
ObjectId("id1"),
ObjectId("id2"),
ObjectId("id3")
]
} } },
{ $project: {
_id: 0,
field0: "$field0",
field1: "$field1",
field2: "$field2",
customField: {
$or:[{
$and: [
{ /*...some condition*/ } ,
{ /*...some condition*/ }
],
},
{
$and: [
{ /*...some condition*/ } ,
{ /*...some condition*/ }
]
}]
}
}
}
])
这按预期工作。
结果
/* 1 */
{
"field0" : "processing",
"field5" : ObjectId("id1"),
"field1" : "val",
"field2" : "val",
"customField" : false
}
/* 2 */
{
"field0" : "processing",
"field5" : ObjectId("id2"),
"field1" : "val",
"field2" : "val",
"customField" : false
}
如果我理解正确,$match 阶段会删除不匹配的 id(比如 id3)。我怎样才能通过创建一个包含为其投影的所有字段的单独文档来在最终输出中获得它?
预期结果
/* 1 */
{
"field0" : "processing",
"field5" : ObjectId("id1"),
"field1" : "val",
"field2" : "val",
"customField" : false
}
/* 2 */
{
"field0" : "processing",
"field5" : ObjectId("id2"),
"field1" : "val",
"field2" : "val",
"customField" : true
}
/* 3 */
/* Note that id3 is unmatched (excluded by $match in result) */
{
"field0" : "processing",
"field5" : ObjectId("id3"),
"field1" : "val",
"field2" : "val",
"customField" : true
}
有没有办法做到这一点?
【问题讨论】:
-
该查询真的不包括第三个文档吗?根据
$match,它也应该包括它!无论如何,您是否需要在同一输出中匹配和不匹配的文档?如果是 - 那么这两种类型之间的区别是什么(就像任何表示匹配文档为真而为不匹配为假的字段)?如果没有这样的事情,那么做$match是没有用的,如果是这种情况,您实际上发布了您的原始要求,以便有人可以帮助您.. -
@whoami 感谢您的回复。抱歉,我也应该解释一下用例。 collectionName 保留要匹配的 id 的临时条目(在 field5 中,它是一个数组)。 $match 阶段将展开文档与传递给它的数组进行比较以寻找匹配项。这是我看不到 id3 并且不确定它是否正确的地方。我想保留无与伦比的价值并将其保存在某个地方。不匹配的值也不应根据 $project 中的条件进行检查,因此不会进一步过滤,应包含在最终结果中。
-
所以你只需要在输出中保留不匹配的文档,同时你需要对匹配的文档做更多的事情吗?所以确实希望在最后为每个文档返回多个文档(正如你正在做的
$unwind),如果是 - 那么放松是有意义的,否则不需要它(所以你正在做的是拆分一个doc 到 field5 上的多个并将它们分类为匹配与不匹配,最终它是具有不同 field5 的同一个文档)?? 无论如何,在您给定的示例文档和查询中,我认为您应该获得带有ObjectId("id3")的文档,不确定您为什么没有获得它 -
@whoami,感谢您的回复。现在我将匹配的结果与临时条目(field5 数组)进行比较,并只添加缺失或不匹配的项目。这似乎是一个肮脏的黑客,但工作。
标签: mongodb mongodb-query aggregation-framework