【问题标题】:Mongo $lookup filter using nested query [duplicate]Mongodb $lookup 过滤器使用嵌套查询[重复]
【发布时间】:2019-05-21 10:52:47
【问题描述】:

我正在使用 mongoDB 的 $lookup 函数,特别是管道语法,以允许我执行一些比我使用的 ORM(Sails/Waterline)允许的更复杂的查询。

我的数据的精简版看起来像....

    // 'job' collection
    {
      "id"      : j1,
      "mediaID" : "ABC1234"
    },
    {
      "id"      : j2,
      "mediaID" : "DEF1234"
    },
    {
      "id"      : j3,
      "mediaID" : "FGH3456"
    }

..和..

    // 'task' collection

    // j1 tasks
    {
      "id"      : "t1",
      "job"     : "j1",
      "taskName": "MOVE",
      "status"  : "COMPLETE"
    },
    {
      "id"      : "t2",
      "job"     : "j1",
      "taskName": "PUBLISH",
      "status"  : "COMPLETE"
    },
    // j2 tasks
    {
      "id"      : "t3",
      "job"     : "j2",
      "taskName": "MOVE",
      "status"  : "FAILED"
    },
    // j3 tasks
    {
      "id"      : "t4",
      "job"     : "j3",
      "taskName": "MOVE",
      "status"  : "COMPLETE"
    }

..其中任务集合通过job.id -> task.job链接到作业集合

我想要实现的是,能够通过job.mediaID 和/或task.status 过滤工作。我目前的查询几乎得到了我想要的,但它没有过滤掉jobs,它只是没有填充tasks 部分。

我目前的查询如下...

    let results = await jobCollection.aggregate([

      // First filter jobs with matching criteria
      {
        $match: {
          $text: {$search: "1234"}
        }
      },

      // Next, link the task collection, and filter by status
      {
        "$lookup": {
          from    : 'task',
          'let'   : {job_id: '$_id'},
          pipeline: [
            {
              $match: {
                $expr: {
                  $and: [
                    // This does the linking of job.id -> task.job_id
                    {$eq: ['$job', '$$job_id']},
                    // This filters out unwanted tasks
                    {$eq: ['$status', 'FAILED']}
                  ]
                }
              }
            }
          ],
          as      : 'tasks'
        }
      }
    ])
    .toArray();

在该示例中,第一阶段将匹配 j1j2,因为它们都包含“1234”,然后我想根据任务状态进一步过滤掉作业,例如,仅 @987654331 @ 有一个包含status==FAILED 的任务,所以我的最终结果就是j2 文档。

我希望这样做。我想我可能只需要在最后添加一些巧妙的投影。谢谢

【问题讨论】:

    标签: mongodb aggregation-framework lookup


    【解决方案1】:

    $lookup 管道内的$matchjobCollection 文档无关。它只过滤 tasks 集合的文档。因此,您必须在$lookup 之后再使用一个$match 阶段来过滤掉ROOT(jobCollection) 文档。

    jobCollection.aggregate([
      { "$match": { "$text": { "$search": "1234" }}},
      { "$lookup": {
        "from": "task",
        "let": { "job_id": "$_id" },
        "pipeline": [
          { "$match": {
            "$expr": {
              "$and": [
                { "$eq": ["$job", "$$job_id"] },
                { "$eq": ["$status", "FAILED"] }
              ]
            }
          }}
        ],
        "as": "tasks"
      }},
      { "$match": { "tasks": { "$ne": [] }}},
    ])
    

    【讨论】:

    • 谢谢,我知道这是我缺少的一些简单的东西。仍在努力解决这一切。
    • 知道如何维护输出中的所有子文档,而不仅仅是匹配的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 2020-07-21
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多