NodeJS中MongoDB聚合查询实现多层引用关联的方案
MongoDB多层引用聚合查询:将UserType嵌入用户对象
需要实现MongoDB的多层引用聚合查询,把每个User对应的UserType信息嵌入到用户对象中,涉及三个关联集合。
集合结构
Insp集合
存储检查记录,包含用户ID数组引用:
[ { "_id": { "$oid": "6359a12fb9450da3d8d8cdd2" }, "REF_Users": [ { "$oid": "6359a0f1b9450da3d8d8cdc7" }, { "$oid": "6359a070f1e84209e0c78fc2" } ], "name": "Once" } ]
Users集合
存储用户信息,包含UserType的ID引用:
[ { "_id": { "$oid": "6359a070f1e84209e0c78fc2" }, "REF_UserType": { "$oid": "63596323b679475de490500a" }, "fName": "Billy" }, { "_id": { "$oid": "6359a0f1b9450da3d8d8cdc7" }, "REF_UserType": { "$oid": "63596323b679475de4905007" }, "fName": "Mike" } ]
UserType集合
存储用户类型信息:
[ { "_id": { "$oid": "63596323b679475de4905007" }, "value": 100, "name": "INS" }, { "_id": { "$oid": "63596323b679475de490500a" }, "value": 200, "name": "CLS" } ]
期望输出
查询后返回的结果需将UserType嵌入对应User对象,结构如下:
{ "_id": "6359a12fb9450da3d8d8cdd2", "people": [ { "_id": "6359a070f1e84209e0c78fc2", "userType": { "_id": "63596323b679475de490500a", "value": 200, "name": "CLS" }, "fName": "Billy" }, { "_id": "6359a0f1b9450da3d8d8cdc7", "userType": { "_id": "63596323b679475de4905007", "value": 100, "name": "INS" }, "fName": "Mike" } ] }
尝试过程
- TRY1:在Compass和Mongo Playground中执行,仅得到部分结果,UserType未嵌入到对应User对象中;
- TRY2、TRY3:在NodeJS中运行时均抛出**"Arguments must be aggregate pipeline operators"**错误。
最终解决方案
通过在$project阶段结合$map、$mergeObjects、$filter等操作符实现需求,完整聚合管道需先通过两次$lookup分别关联Users和UserType集合(生成peopleLookup和userTypeLookup字段),再用以下$project处理数据:
{ $project:{ 'people': { $map: { input: '$peopleLookup', as: 'tempPeople', in: { $mergeObjects: [ '$$tempPeople', { 'userType': { $first: { $filter: { input: '$userTypeLookup', cond: { $eq: ['$$tempPeople.REF_UserType', '$$this._id'], }, }, }, }, }, ], }, }, }, } }
代码说明
$map遍历peopleLookup中的每个用户对象;$filter从userTypeLookup中筛选出与当前用户REF_UserType匹配的UserType记录,$first取唯一匹配项;$mergeObjects将原用户对象与筛选得到的UserType对象合并,生成包含userType字段的新用户对象;- 最终将处理后的数组命名为
people字段输出。
内容的提问来源于stack exchange,提问作者MrLister
相关产品推荐
相关产品推荐

