如何在mongodb聚合输出中包含不匹配的文档?
我在下面写了聚合,它是在集合中展开一个数组,然后检查每个展开的文档是否与给定对象id数组中的任何元素匹配。投影时,生成的集合将通过条件对其进行进一步过滤如何在mongodb聚合输出中包含不匹配的文档?,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,我在下面写了聚合,它是在集合中展开一个数组,然后检查每个展开的文档是否与给定对象id数组中的任何元素匹配。投影时,生成的集合将通过条件对其进行进一步过滤 db.collectionName.aggregate([ { $unwind: { path: "$field5", preserveNullAndEmptyArrays: true } }, { $match: { field5: { $in:
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 stage会删除不匹配的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
}
有没有办法做到这一点 是的,你可以做到,但这有点棘手
$facet
将有助于实现这一目标
db.collection.aggregate([
{
$facet:{
"matched":[
{
$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*/ }
]
}]
}
}
}
],
"unmatched":[
{
$unwind:{
path: "$field5",
preserveNullAndEmptyArrays: true
}
},
{
$match:{
field5: {
$nin:
[
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*/ }
]
}]
}
}
}
]
}
},
{
$project:{
"all":{
$concatArrays:[
"$matched",
"$unmatched"
]
}
}
},
{
$unwind:"$all"
},
{
$replaceRoot:{
newRoot:"$all"
}
}
]).pretty()
希望这将有助于您的用例
此外,您还可以根据需要更新这两个方面(“匹配”和“未匹配”)
您可以找到有关$facet的更多信息是的,您可以实现这一点,但这有点棘手
$facet
将有助于实现这一目标
db.collection.aggregate([
{
$facet:{
"matched":[
{
$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*/ }
]
}]
}
}
}
],
"unmatched":[
{
$unwind:{
path: "$field5",
preserveNullAndEmptyArrays: true
}
},
{
$match:{
field5: {
$nin:
[
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*/ }
]
}]
}
}
}
]
}
},
{
$project:{
"all":{
$concatArrays:[
"$matched",
"$unmatched"
]
}
}
},
{
$unwind:"$all"
},
{
$replaceRoot:{
newRoot:"$all"
}
}
]).pretty()
希望这将有助于您的用例
此外,您还可以根据需要更新这两个方面(“匹配”和“未匹配”)
您可以找到有关$facet的更多信息该查询是否真的排除了第三个文档?根据
$match
的规定,它也应该包括它!!无论如何,您是否需要在同一输出中使用匹配和不匹配的文档?如果是-那么这两种类型之间的区别是什么(类似于任何表示匹配文档为true的字段和表示未匹配文档为false的字段)?如果没有这样的事情,那么做$match
是没有用的,如果是这样的话,你实际上发布了你的原始需求,以便有人可以在这方面帮助你..@whoami谢谢你的回复。抱歉,我可能也应该解释一下这个用例。collectionName保留要匹配的id临时条目(在field5中,它是一个数组)。$match阶段将展开文档与传递给它的数组进行比较,以查找匹配项。这就是我没有看到id3的地方,也不确定它是否正确。我想保留无与伦比的价值,并将其保留在某个地方。不匹配的值也不会根据$project中的条件进行检查,因此不会进一步筛选,并应包含在最终结果中。因此,您只需在输出中保留不匹配的文档,同时还需要对匹配的文档执行更多操作?因此,您是否希望在结束时为每个单独的文档返回多个文档(正如您正在执行的$unwind
),如果是,则有必要展开,否则就不需要(因此,您所做的是将字段5上的单个文档拆分为多个文档,并将它们分类为匹配与不匹配,一天结束时,它是具有不同字段5的同一个文档)?? 无论如何,在您给定的示例文档和查询中,我认为您应该使用ObjectId(“id3”)
获取文档,但不确定您为什么不获取it@whoami,谢谢你的回复。现在,我将匹配的结果和临时条目(field5数组)进行比较,并只向其中添加缺少或不匹配的项。这似乎是一个肮脏的黑客行为,但正在发挥作用。这个查询真的排除了第三个文档吗?根据$match
的规定,它也应该包括它!!无论如何,您是否需要在同一输出中使用匹配和不匹配的文档?如果是-那么这两种类型之间的区别是什么(类似于任何表示匹配文档为true的字段和表示未匹配文档为false的字段)?如果没有这样的事情,那么做$match
是没有用的,如果是这样的话,你实际上发布了你的原始需求,以便有人可以在这方面帮助你..@whoami谢谢你的回复。抱歉,我可能也应该解释一下这个用例。collectionName保留要匹配的id临时条目(在field5中,它是一个数组)。$match阶段将展开文档与传递给它的数组进行比较,以查找匹配项。这就是我没有看到id3的地方,也不确定它是否正确。我想保留无与伦比的价值,并将其保留在某个地方。不匹配的值也不会根据$project中的条件进行检查,因此不会进一步筛选,并应包含在最终结果中。因此,您只需在输出中保留不匹配的文档,同时还需要对匹配的文档执行更多操作?因此,您是否希望在结束时为每个单独的文档返回多个文档(正如您正在执行的$unwind
),如果是,则有必要展开,否则就不需要(因此,您所做的是将字段5上的单个文档拆分为多个文档,并将它们分类为匹配与不匹配,一天结束时,它是具有不同字段5的同一个文档)?? 无论如何,在您给定的示例文档和查询中,我认为您应该使用ObjectId(“id3”)
获取文档,但不确定您为什么不获取it@whoami,谢谢你的回复。现在,我将匹配的结果和临时条目(field5数组)进行比较,并只向其中添加缺少或不匹配的项。这似乎是一个肮脏的黑客,但工作。$facets看起来很有趣。我一定要试试。到目前为止,我正在将匹配的结果与临时条目(field5数组)进行比较,并只向其中添加缺少或不匹配的项。谢谢。关于$facet
还有一件事是它同时运行,即;facet中的所有阶段将同时运行。$facets看起来很有趣。我一定要试试。到目前为止,我正在将匹配的结果与临时条目(field5数组)进行比较,并只向其中添加缺少或不匹配的项。谢谢。关于$facet
还有一件事是它同时运行,即;方面中的所有阶段将同时运行。