首页 > 解决方案 > MongoDB 聚合查找从 localField 到结果的附加字段

问题描述

我在 MongoDB ( mongoplayground ) [ characters, guilds]中有以下集合

我想做一个$lookup,它将rank向结果文档添加字段,如下所示:

    "members_t": [
      {
        "_id": ObjectId("5a934e000102030405000000"),
        "level": 20,
        "name": "test1",
        "rank": 1
      },
      {
        "_id": ObjectId("5a934e000102030405000001"),
        "level": 40,
        "name": "test2",
        "rank": 2
      }
    ]

$lookup语法对此无能为力,但以下使用新语法的查询会在tested字段中返回一个空数组(即使没有$addFields阶段):

  {
    $lookup: {
      from: "characters",
      let: {
        members_name: "$members.name",
        rank: "$members.rank"
      },
      pipeline: [
        {
          $match: {
            name: "$$members_name"
          }
        }
      ],
      as: "tested"
    }
  }

那么,是否有任何选项可以在阶段之后添加额外的字段$lookup

(Mongo -v 4.2.3,所以问题与新语法支持无关)

标签: javascriptmongodbmongoosemongodb-queryaggregation-framework

解决方案


你几乎接近解决它。由于members是一个数组,因此您需要将其传递给$lookup每个字符,然后有条件地加入它$reduce(您也可以这样做$filter,但我们需要额外的阶段)。

注意: 解释为什么我们需要使用$expr内部$lookup管道。

试试这个:

db.guilds.aggregate([
  {
    $lookup: {
      from: "characters",
      let: {
        members: "$members"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $in: [
                "$name",
                "$$members.name"
              ]
            }
          }
        },
        {
          $addFields: {
            rank: {
              $reduce: {
                input: "$$members",
                initialValue: null,
                in: {
                  $cond: [
                    {
                      $eq: [
                        "$$this.name",
                        "$name"
                      ]
                    },
                    "$$this.rank",
                    "$$value"
                  ]
                }
              }
            }
          }
        }
      ],
      as: "members_t"
    }
  }
])

Mongo游乐场


推荐阅读