如何在MongoDB中关联两个无序数组并合并指定字段?
解决方案
针对你需要将authorsDetails中的name字段按id匹配合并到authors数组(不依赖数组顺序)的需求,可以通过以下MongoDB聚合管道实现:
const pipeline = [ { $addFields: { // 将authorsDetails转换为以id为键、name为值的映射对象 authorNameMap: { $arrayToObject: { $map: { input: "$authorsDetails", as: "detail", in: { k: { $toString: "$$detail.id" }, // 转换为字符串作为对象键 v: "$$detail.name" } } } } } }, { $addFields: { // 遍历authors数组,匹配对应的name字段并合并 authors: { $map: { input: "$authors", as: "author", in: { $mergeObjects: [ "$$author", { name: { $getField: { field: { $toString: "$$author.id" }, input: "$authorNameMap" } } } ] } } } } }, { // 移除临时生成的映射对象和原authorsDetails字段 $project: { authorNameMap: 0, authorsDetails: 0 } } ];
步骤说明
- 生成映射对象:通过
$arrayToObject和$map将authorsDetails转换为{ "1": "Author 1", "2": "Author 2" }格式的对象,这样可以通过作者id快速查找对应的name,彻底摆脱数组顺序依赖。 - 合并字段:使用
$map遍历authors数组,对每个元素通过$mergeObjects合并原字段和从映射对象中获取的name字段(注意将数字id转为字符串匹配对象键)。 - 清理字段:最后用
$project移除临时的authorNameMap和不再需要的authorsDetails字段。
替代方案(兼容低版本MongoDB)
如果你的MongoDB版本不支持$getField(MongoDB 5.0+支持),可以用$filter配合$arrayElemAt实现匹配:
const pipeline = [ { $addFields: { authors: { $map: { input: "$authors", as: "author", in: { $mergeObjects: [ "$$author", { name: { $getField: { field: "name", input: { $arrayElemAt: [ { $filter: { input: "$authorsDetails", cond: { $eq: ["$$this.id", "$$author.id"] } } }, 0 ] } } } } ] } } } } }, { $project: { authorsDetails: 0 } } ];
这个方案通过$filter在authorsDetails中找到与当前author id匹配的元素,再提取name字段,不需要提前生成映射对象,但性能上不如映射对象方案(尤其是数组较大时)。
内容的提问来源于stack exchange,提问作者Loudrous
相关产品推荐
相关产品推荐

