合并嵌套在数组 mongoose 中的对象内的 $lookup 值

Posted

技术标签:

【中文标题】合并嵌套在数组 mongoose 中的对象内的 $lookup 值【英文标题】:Merge $lookup value inside objects nested in array mongoose 【发布时间】: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' ,
          ,
        ,
      ,
    ,
 ])
  

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

【问题讨论】:

【参考方案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

【讨论】:

以上是关于合并嵌套在数组 mongoose 中的对象内的 $lookup 值的主要内容,如果未能解决你的问题,请参考以下文章

Nodejs mongoose根据对象属性选择嵌套数组中的对象

Mongoose 嵌套对象数组中的唯一值

Mongoose 嵌套对象数组中的唯一值

如何使用 Node.js 和 Mongoose 将对象添加到嵌套数组

mongoose 怎么插入嵌套数组

Mongoose:通过 findOneAndUpdate 查询使用嵌套对象数组的总和更新父子数据属性不起作用