MongoDB聚合中如何匹配数组内含指定键的文档
解决方案
我来帮你搞定这个问题!首先针对你在$match阶段的需求,完全可以不用$unwind就能高效筛选出目标文档,后续的分组统计也能兼顾性能。
第一步:正确的$match筛选语句
要匹配taglist数组中至少包含一个带color键元素的文档,你可以用$exists操作符结合MongoDB的数组点符号实现,这是性能最优的方式:
db.items.aggregate([ {$match: {"taglist.color": {$exists: true}}} ])
为什么这个写法管用?
- MongoDB的数组点符号(
taglist.color)会自动遍历数组内的每个元素,检查是否存在指定键。 $exists: true的逻辑是:只要数组里有至少一个元素包含color键,不管这个键的值是什么,该文档都会被匹配出来,完美符合你的需求。
第二步:完整的聚合管道(含分组统计)
既然你还需要按color分组统计总成本(比如示例文档要输出red: $7, green: $7),可以在$match之后添加几个阶段,尽可能减少不必要的数据处理:
db.items.aggregate([ // 1. 先筛选出符合条件的文档 {$match: {"taglist.color": {$exists: true}}}, // 2. 过滤taglist,只保留带color键的元素(减少后续处理的数据量) {$project: { cost: 1, taglist: {$filter: { input: "$taglist", cond: {$exists: ["$$this.color", true]} }} }}, // 3. 展开处理后的taglist数组(这一步是必要的,因为要按单个color分组) {$unwind: "$taglist"}, // 4. 按color分组,累加总成本 {$group: { _id: "$taglist.color", totalCost: {$sum: "$cost"} }}, // 可选:重命名字段让结果更直观 {$project: { color: "$_id", totalCost: 1, _id: 0 }} ])
结果说明
针对你提供的示例文档,执行上述管道后会得到:
[ { "totalCost" : 7, "color" : "red" }, { "totalCost" : 7, "color" : "green" } ]
内容的提问来源于stack exchange,提问作者Rorschach
相关产品推荐
相关产品推荐

