MongoDB集合提取字符串数组唯一值:$reduce使用报错排查
MongoDB提取集合中数组的所有唯一值问题
问题场景
给定集合文档:
{ _id: 1, values: ['1','2','4'] }, { _id: 2, values: ['1','3','5'] }
需要提取所有文档中values数组里的唯一字符串,期望输出:['1','2','3','4','5']
错误尝试及原因
尝试使用$reduce编写的聚合代码:
db.collection .aggregate([ { $project: { 'values': { $reduce: { input: '$values', initialValue: [], in: { $concatArrays: ['$$value', '$$this'] } } } } } ])
执行后报错:$concatArrays only supports arrays, not string
错误原因:$reduce遍历values数组时,$$this指代的是数组中的单个字符串元素,而$concatArrays要求两个参数都必须是数组,直接传入字符串就会触发类型错误。
正确解决方案
方案一:$unwind + $group(推荐,直观高效)
通过拆分数组元素再分组去重,逻辑清晰且性能稳定:
db.collection.aggregate([ // 将每个数组元素拆分为独立文档 { $unwind: "$values" }, // 分组收集所有唯一值 { $group: { _id: null, uniqueValues: { $addToSet: "$values" } } }, // 可选:移除_id字段,只保留结果数组 { $project: { _id: 0 } } ])
$addToSet会自动忽略重复值,最终得到去重后的数组。
方案二:$group + $setUnion(简洁写法)
直接合并所有文档的数组并去重,步骤更少:
db.collection.aggregate([ // 收集所有文档的values数组 { $group: { _id: null, allArrays: { $push: "$values" } } }, // 使用$setUnion合并数组并去重 { $project: { uniqueValues: { $setUnion: "$allArrays" }, _id: 0 } } ])
$setUnion支持接收数组的数组,直接返回合并后的唯一值集合。
方案三:修复$reduce的写法(不推荐,步骤繁琐)
如果一定要用$reduce实现,需要将单个元素包装为数组后再拼接,最后合并去重:
db.collection.aggregate([ { $project: { values: { $reduce: { input: "$values", initialValue: [], // 将单个字符串包装为数组再拼接 in: { $concatArrays: ["$$value", ["$$this"]] } } } } }, // 收集所有文档处理后的数组 { $group: { _id: null, allValues: { $push: "$values" } } }, // 合并所有数组 { $project: { allValues: { $reduce: { input: "$allValues", initialValue: [], in: { $concatArrays: ["$$value", "$$this"] } } } } }, // 去重得到结果 { $project: { uniqueValues: { $setUnion: ["$allValues"] }, _id: 0 } } ])
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

