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" ] }
                            ]
                        }
                    }
                }
            }
        }
    }
])

免责声明:您的数据/聚合中有两个不同的字段名称:taskNametaskCode。我决定使用第一个。

您可以使用 $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
    }}
])