MongoDB:过滤数组并求和已购书籍volume对象的price字段
统计MongoDB文档内已购书籍总花费的解决方案
嘿,针对你要统计MongoDB中文档内已购书籍总花费的需求,我给你整理了几种实用的聚合方案,都是日常开发中常用的写法,你可以根据自己的场景选择:
首先先明确下假设的文档结构(方便你对应自己的集合调整):
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "username": "john_doe", "volumes": [ { "title": "MongoDB权威指南", "bought": true, "price": 89.9 }, { "title": "JavaScript高级程序设计", "bought": false, "price": 129.0 }, { "title": "Python数据分析", "bought": true, "price": 79.5 } ] }
方案1:分步过滤+求和(可读性高)
这个方案把数组过滤和求和拆分成不同阶段,逻辑清晰,适合新手理解:
db.your_collection_name.aggregate([ // 可选:如果你需要统计特定文档(比如某个用户),添加这个阶段定位目标文档 { $match: { username: "john_doe" } }, // 第一步:过滤出已购买的书籍项 { $addFields: { purchasedVolumes: { $filter: { input: "$volumes", cond: { $eq: ["$$this.bought", true] } } } } }, // 第二步:对已购书籍的price字段求和 { $project: { username: 1, // 保留你需要的其他字段 totalSpent: { $sum: "$purchasedVolumes.price" } } } ])
阶段说明:
- $match:用来精准定位你要统计的文档,不需要全局统计的话可以跳过这个阶段。
- $addFields:新增
purchasedVolumes字段,通过$filter遍历volumes数组,只保留bought为true的元素($$this代表数组中的当前遍历元素)。 - $project:用
$sum对过滤后的数组中的price值求和,得到总花费totalSpent,同时保留你需要展示的其他字段。
方案2:合并过滤与求和(更简洁)
如果追求代码紧凑,可以把过滤、提取价格、求和合并到一个$project阶段:
db.your_collection_name.aggregate([ { $match: { username: "john_doe" } }, // 同样可选 { $project: { username: 1, totalSpent: { $sum: { $map: { input: { $filter: { input: "$volumes", cond: { $eq: ["$$this.bought", true] } } }, as: "item", in: "$$item.price" } } } } } ])
这里先用$filter筛选已购书籍,再用$map把筛选后的元素转换成对应的price值数组,最后用$sum直接对这个数组求和。
方案3:统计集合内所有文档的总花费
如果需要统计整个集合中所有用户的已购书籍总花费,可以用$group阶段实现:
db.your_collection_name.aggregate([ // 先提取每个文档的已购书籍价格数组 { $addFields: { purchasedPrices: { $map: { input: { $filter: { input: "$volumes", cond: { $eq: ["$$this.bought", true] } } }, in: "$$this.price" } } } }, // 全局分组求和 { $group: { _id: null, // _id设为null表示全局分组 overallTotalSpent: { $sum: { $sum: "$purchasedPrices" } } } } ])
这里的嵌套$sum是因为每个文档的purchasedPrices是一个数组,内层$sum计算单个文档的总花费,外层$sum累加所有文档的结果。
内容的提问来源于stack exchange,提问作者Pascal Klose
相关产品推荐
相关产品推荐

