MongoDB如何将$lookup返回数组的元素投影为文档普通属性
解决方案
$lookup 关联返回的as字段默认是数组类型,直接通过点语法取嵌套字段时,会返回所有元素对应字段组成的数组,想要拿到单个非数组值可通过以下方案实现:
方案1:使用$first取数组首元素属性(MongoDB 4.4+ 支持)
如果确认每个departments文档仅关联1条employees数据,直接在$project阶段用$first操作符取数组首个元素的对应字段即可,是性能最优的方案:
db.departments.aggregate([{ $lookup: { from: 'employees', localField: 'dep_id', foreignField: 'department', as: 'emps' } }, { $project: { _id: 0, emp_id: 1, salary: 1, emp_name: { $first: '$emps.name' }, username: { $first: '$emps.username' } } }])
方案2:$unwind拆分数组后投影(全版本兼容)
如果使用的MongoDB版本低于4.4不支持$first在$project中直接使用,或者存在一对多关联需要把每条关联数据拆分为独立文档,可在$lookup后新增$unwind阶段:
db.departments.aggregate([{ $lookup: { from: 'employees', localField: 'dep_id', foreignField: 'department', as: 'emps' } }, { // 拆分数组,preserveNullAndEmptyArrays 配置可保留关联结果为空的文档 $unwind: { path: '$emps', preserveNullAndEmptyArrays: true } }, { $project: { _id: 0, emp_id: 1, salary: 1, emp_name: '$emps.name', username: '$emps.username' } }])
可选优化:批量提取关联文档所有字段
如果需要把emps的所有字段都合并到根文档,无需逐个声明字段,可使用$mergeObjects + $replaceRoot实现:
db.departments.aggregate([{ $lookup: { from: 'employees', localField: 'dep_id', foreignField: 'department', as: 'emps' } }, { $unwind: { path: '$emps', preserveNullAndEmptyArrays: true } }, { $replaceRoot: { newRoot: { $mergeObjects: [ '$$ROOT', '$emps' ] } } }, { // 移除不需要的字段 $project: { _id: 0, emps: 0, department: 0 // 可按需移除employees表中不需要的字段 } }])
内容的提问来源于stack exchange,提问作者Rishi
相关产品推荐
相关产品推荐

