继this问题之后,我希望根据相关子文档中的值来过滤父文档列表。
给出以下mongoDB集合。...
// 'job' collection
{
"id" : j1,
"mediaID" : "ABC1234"
},
{
"id" : j2,
"mediaID" : "DEF1234"
}
.. and ..
// 'task' collection
// j1 tasks
{
"id" : "t1",
"job" : "j1",
"taskName": "MOVE",
"status" : "COMPLETE"
},
{
"id" : "t2",
"job" : "j1",
"taskName": "PUBLISH",
"status" : "FAILED"
},
// j2 tasks
{
"id" : "t3",
"job" : "j2",
"taskName": "MOVE",
"status" : "COMPLETE"
},
{
"id" : "t4",
"job" : "j2",
"taskName": "PUBLISH",
"status" : "COMPLETE"
}
..其中任务集合通过job.id-> task.job
链接到任务集合我有一个聚合查询,该查询将根据子集合中的条件过滤job
集合。我正在使用Mongo的$lookup
的管道语法,并且有类似这样的查询。...
db.getCollection("job").aggregate(
[
{
"$lookup": {
"from" : "task",
"let" : {
"job_id": "$_id"
},
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{
// link job.id to task.job
"$eq": ["$job", "$$job_id"]
},
{
// Filter taskName
"$eq": ["$taskName", "PUBLISH"]
},
{
// Filter by status
"$eq": ["$status", "FAILED"]
}
]
}
}
}
],
"as" : "tasks"
}
},
{
// Remove ROOT docs that do not meet 'task' criteria
"$match": {
"tasks": {"$ne": []}
}
}
]
);
这很好用,只是我希望结果的父级的所有所有子文档返回到结果中,而不仅仅是匹配的子文档。
例如,上面的查询给了我这个...
{
"id" : j1,
"mediaID" : "ABC1234"
"tasks" : [
{
"id" : "t2",
"job" : "j1",
"taskName": "PUBLISH",
"status" : "FAILED"
},
]
},
..但是我想要这个...
{
"id" : j1,
"mediaID" : "ABC1234"
"tasks" : [
{
"id" : "t1",
"job" : "j1",
"taskName": "MOVE",
"status" : "COMPLETE"
},
{
"id" : "t2",
"job" : "j1",
"taskName": "PUBLISH",
"status" : "FAILED"
},
]
},
我有墨水,有时需要使用$push
,但很困惑!任何帮助表示赞赏。
答案 0 :(得分:1)
您应该将过滤逻辑移出$lookup
,并运行$match作为下一个管道阶段。在那里,您可以使用$anyElementTrue运算符来检查是否存在带有所需值的子文档:
db.job.aggregate([
{
$lookup: {
from: "task",
localField: "id",
foreignField: "job",
as: "tasks"
}
},
{
$match: {
$expr: {
$anyElementTrue: {
$map: {
input: "$tasks",
in: {
$and: [
{ $eq: [ "$$this.taskName", "PUBLISH" ] },
{ $eq: [ "$$this.status", "FAILED" ] }
]
}
}
}
}
}
}
])
免责声明:您的数据/聚合中有两个不同的字段名称:taskName
和taskCode
。我决定使用第一个。
答案 1 :(得分:0)
您可以使用$ addFields。
db.job.aggregate([
{$lookup: {from: 'task', localField: 'id', foreignField: 'job', as: 'taskList'}},
{$addFields: {
tasks: {
$filter: {
input: '$taskList',
as: 't',
cond: { $and: [
{$eq: ['$$t.taskCode', 'PUBLISH']},
{$eq: ['$$t.status', 'FAILED']}
]}
}
}
}},
{$project: {
_id: 1,
mediaID: 1,
tasks: 1
}}
])