Mongodb聚合查找查询-return所有子文档
Mongodb aggregation lookup query - return all sub-documents
根据 问题,我希望根据相关子文档中的值过滤父文档列表。
给定以下 mongoDB 个集合....
// 'job' collection
{
"id" : j1,
"mediaID" : "ABC1234"
},
{
"id" : j2,
"mediaID" : "DEF1234"
}
..和..
// '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
,但我很困惑!任何帮助表示赞赏。
您应该将过滤逻辑从 $lookup
和 运行 $match as a next pipeline stage. There you can use $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
。我决定使用第一个。
您可以使用 $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
}}
])
根据
给定以下 mongoDB 个集合....
// 'job' collection
{
"id" : j1,
"mediaID" : "ABC1234"
},
{
"id" : j2,
"mediaID" : "DEF1234"
}
..和..
// '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
,但我很困惑!任何帮助表示赞赏。
您应该将过滤逻辑从 $lookup
和 运行 $match as a next pipeline stage. There you can use $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
。我决定使用第一个。
您可以使用 $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
}}
])