如何将数组转换为 mongodb/mongoose 聚合中的对象?

How to transform array to objects in mongodb/mongoose aggregation?

共有三个合集。

离开

请假

用户

在休假集合上执行查找阶段后:

Leave.aggregate([
    $lookup: {
        from: 'leaveapprovals',
        localField: '_id',
        foreignField: 'leave',
        as: 'approverRecommender'
    }
])
{
    _id: ObjectId('6262851ab059b81fd9076532'),
    user: ObjectId('21ca9490192add08fa385aec'),
    status: "pending",
    approverRecommender: [
        {
            _id: ObjectId('6262851ab059b81fd907653d'),
            leave: ObjectId('6262851ab059b81fd9076532'),
            auditUser: ObjectId('61ca9490192add08fa385aeb'),
            role: "recommender"    
        },
        {
            _id: ObjectId('6262851ab059b81fd907653d'),
            leave: ObjectId('6262851ab059b81fd9076532'),
            auditUser: ObjectId('71ca9490192add08fa385aec'),
            role: "approver"    
        }
    ]
}

我想要得到的结果是:

{
    _id: ObjectId('6262851ab059b81fd9076532'),
    user: ObjectId('21ca9490192add08fa385aec'),
    status: "pending",
    recommender: {
        _id: ObjectId('61ca9490192add08fa385aeb'),
        name: "Andrew"
    },
    approver: {
        _id: ObjectId('71ca9490192add08fa385aec'),
        name: "James"
    }
}

如何改造?

  1. $lookup - 需要一个嵌套的 $lookup。首先 $lookup 使用管道加入 leaveleaveapprovals 集合。而内部 $lookup 加入 user 集合和 return auditUserrole 字段。

  2. $set -

    2.1。对于 approver 字段,为 approver 角色过滤 approverRecommender 数组字段,并通过 $first.

    获取第一个文档

    2.2。对于 recommender 字段,过滤 recommender 角色的 approverRecommender 数组字段,并通过 $first.

    获取第一个文档
  3. $project - 修饰输出文档。使用 $first 到 return approverrecommender 的第一个文档作为结果 2 的两个字段 return 作为数组。

db.leave.aggregate([
  {
    $lookup: {
      from: "leaveapprovals",
      let: {
        leaveId: "$_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$$leaveId",
                "$leave"
              ]
            }
          }
        },
        {
          $lookup: {
            from: "user",
            localField: "auditUser",
            foreignField: "_id",
            as: "auditUser"
          }
        },
        {
          $project: {
            auditUser: 1,
            role: 1
          }
        }
      ],
      as: "approverRecommender"
    }
  },
  {
    "$set": {
      approver: {
        "$first": {
          "$filter": {
            "input": "$approverRecommender",
            "cond": {
              $eq: [
                "$$this.role",
                "approver"
              ]
            }
          }
        }
      },
      recommender: {
        "$first": {
          "$filter": {
            "input": "$approverRecommender",
            "cond": {
              $eq: [
                "$$this.role",
                "recommender"
              ]
            }
          }
        }
      }
    }
  },
  {
    "$set": {
      approver: {
        "$first": {
          "$filter": {
            "input": "$approverRecommender",
            "cond": {
              $eq: [
                "$$this.role",
                "approver"
              ]
            }
          }
        }
      },
      recommender: {
        "$first": {
          "$filter": {
            "input": "$approverRecommender",
            "cond": {
              $eq: [
                "$$this.role",
                "recommender"
              ]
            }
          }
        }
      }
    }
  },
  {
    $project: {
      _id: 1,
      user: 1,
      status: 1,
      "approver": {
        $first: "$approver.auditUser"
      },
      "recommender": {
        $first: "$recommender.auditUser"
      }
    }
  }
])

Sample Mongo Playground