我在下面的聚合中写道,该聚合将展开集合中的数组,然后检查每个展开的文档是否与给定对象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
}
有没有办法做到这一点?
答案 0 :(得分:0)
是的,您可以实现,但这有点棘手。
$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 here
的更多信息