【问题标题】:Merge $lookup value inside objects nested in array mongoose合并嵌套在数组 mongoose 中的对象内的 $lookup 值
【发布时间】:2022-01-11 12:15:15
【问题描述】:

所以我有 2 个模型 userform

用户架构

firstName: {
  type: String,
  required: true,
},
lastName: {
  type: String,
  required: true,
},
email: {
  type: String,
  required: true,
}

表单架构

 approvalLog: [
      {
        attachments: {
          type: [String],
        },
        by: {
          type: ObjectId,
        },
        comment: {
          type: String,
        },
        date: {
          type: Date,
        },
      },
    ],
 userId: {
      type: ObjectId,
      required: true,
    },
... other form parameters

返回表单时,我试图将approvalLog 中每个用户的用户信息汇总到各自的对象中,如下所示。

{
...other form info
 approvalLog: [
    {
      attachments: [],
      _id: '619cc4953de8413b548f61a6',
      by: '619cba9cd64af530448b6347',
      comment: 'visit store for disburement',
      date: '2021-11-23T10:38:13.565Z',
      user: {
        _id: '619cba9cd64af530448b6347',
        firstName: 'admin',
        lastName: 'user',
        email: 'admin@mail.com',
      },
    },
    {
      attachments: [],
      _id: '619cc4ec3ea3e940a42b2d01',
      by: '619cbd7b3de8413b548f61a0',
      comment: '',
      date: '2021-11-23T10:39:40.168Z',
      user: {
        _id: '619cbd7b3de8413b548f61a0',
        firstName: 'sam',
        lastName: 'ben',
        email: 'sb@mail.com',
      },
    },
    {
      attachments: [],
      _id: '61a9deab8f472c52d8bac095',
      by: '61a87fd93dac9b209096ed94',
      comment: '',
      date: '2021-12-03T09:08:59.479Z',
      user: {
        _id: '61a87fd93dac9b209096ed94',
        firstName: 'john',
        lastName: 'doe',
        email: 'jd@mail.com',
      },
    },
  ],
}

我当前的代码是

 Form.aggregate([
      {
      $lookup: {
        from: 'users',
        localField: 'approvalLog.by',
        foreignField: '_id',
        as: 'approvedBy',
      },
    },
    { $addFields: { 'approvalLog.user': { $arrayElemAt: ['$approvedBy', 0] } } },
 ])

但它只为所有对象返回相同的用户。如何为每个索引附加匹配的用户?

我也试过

Form.aggregate([
      {
      $lookup: {
        from: 'users',
        localField: 'approvalLog.by',
        foreignField: '_id',
        as: 'approvedBy',
      },
    },
    {
      $addFields: {
        approvalLog: {
          $map: {
            input: { $zip: { inputs: ['$approvalLog', '$approvedBy'] } },
            in: { $mergeObjects: '$$this' },
          },
        },
      },
    },
 ])
  

这会将正确的用户添加到他们各自的对象中,但我只能将其添加到根对象而不是新对象。

【问题讨论】:

    标签: mongodb mongoose aggregation-framework


    【解决方案1】:

    你可以试试这个方法,

    • $map 迭代 approvalLog 的循环
    • $filter 迭代 approvedBy 数组的循环并搜索用户 ID by
    • $arrayElemAt 从上面的过滤结果中获取第一个元素
    • $mergeObjects 合并approvalLog 和过滤用户的当前对象属性
    • $$REMOVE 现在不需要 approvedBy
    await Form.aggregate([
      {
        $lookup: {
          from: "users",
          localField: "approvalLog.by",
          foreignField: "_id",
          as: "approvedBy"
        }
      },
      {
        $addFields: {
          approvalLog: {
            $map: {
              input: "$approvalLog",
              as: "a",
              in: {
                $mergeObjects: [
                  "$$a",
                  {
                    user: {
                      $arrayElemAt: [
                        {
                          $filter: {
                            input: "$approvedBy",
                            cond: { $eq: ["$$a.by", "$$this._id"] }
                          }
                        },
                        0
                      ]
                    }
                  }
                ]
              }
            }
          },
          approvedBy: "$$REMOVE"
        }
      }
    ])
    

    Playground


    第二种方法使用$unwind

    • $unwind 解构 approvalLog 数组
    • $lookup 有用户收藏
    • $addFields$arrayElemAt 从查找结果中获取第一个元素
    • $group by _id 并重构 approvalLog 数组并获取其他所需属性的第一个值
    await Form.aggregate([
      { $unwind: "$approvalLog" },
      {
        $lookup: {
          from: "users",
          localField: "approvalLog.by",
          foreignField: "_id",
          as: "approvalLog.user"
        }
      },
      {
        $addFields: {
          "approvalLog.user": {
            $arrayElemAt: ["$approvalLog.user", 0]
          }
        }
      },
      {
        $group: {
          _id: "$_id",
          approvalLog: { $push: "$approvalLog" },
          userId: { $first: "$userId" },
          // add your other properties like userId
        }
      }
    ])
    

    Playground

    【讨论】:

      猜你喜欢
      • 2021-08-09
      • 2018-11-30
      • 2021-07-23
      • 1970-01-01
      • 2013-04-02
      • 2017-11-17
      相关资源
      最近更新 更多