合并嵌套在数组 mongoose 中的对象内的 $lookup 值
Posted
技术标签:
【中文标题】合并嵌套在数组 mongoose 中的对象内的 $lookup 值【英文标题】:Merge $lookup value inside objects nested in array mongoose 【发布时间】:2022-01-11 12:15:15 【问题描述】:所以我有 2 个模型 user
和 form
。
用户架构
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根据对象属性选择嵌套数组中的对象