MongoDB聚合计算平均时长时如何获取全部字段?
解决MongoDB聚合结果中保留全部字段的问题
我来帮你搞定这个问题~你当前的聚合查询里,$group阶段只返回了分组用的SWITCHID、STATUS和计算出的avgduration,所以其他字段都被过滤掉了。这里有两种实用方案,根据你的实际场景选择:
方案一:在$group里直接保留固定字段(适合同分组内字段值一致的情况)
如果同一个分组(相同SWITCHID+STATUS)下的其他字段(比如设备ID、位置信息这类)都是固定不变的,你可以用$first或$last操作符把这些字段加到$group的输出里。比如你想保留DEVICEID、LOCATION,可以修改你的聚合代码:
db.lights.aggregate([ { $match: { CREATE_DATE: { $gte: ISODate("2018-01-24T20:05:30.000Z"), $lt: ISODate("2018-02-24T20:05:30.000Z") } } }, { $addFields: { offduration: { $divide: [ { $subtract: ["$RECEIVEDDATE", "$CREATE_DATE"] }, 3600000 ] } } }, { "$group": { _id: { SWITCHID: "$SWITCHID", STATUS: "$STATUS" }, avgduration: { $avg: "$offduration" }, // 补全你原本的平均计算逻辑 // 把需要保留的字段加在这里,用$first取分组内第一个文档的对应值 DEVICEID: { $first: "$DEVICEID" }, LOCATION: { $first: "$LOCATION" }, CREATE_DATE: { $first: "$CREATE_DATE" } } }, // 可选步骤:把_id里的字段提取到顶层,让结果结构更清爽 { $project: { _id: 0, SWITCHID: "$_id.SWITCHID", STATUS: "$_id.STATUS", avgduration: 1, DEVICEID: 1, LOCATION: 1, CREATE_DATE: 1 } } ])
方案二:先算平均值,再关联原始文档(适合同分组内字段值多变的情况)
如果同一个分组下有多个不同的字段值,你需要先完成分组计算,再通过$lookup关联原始集合,把所有相关文档的字段都拉回来。这种方式会返回每个分组对应的所有原始数据:
db.lights.aggregate([ { $match: { CREATE_DATE: { $gte: ISODate("2018-01-24T20:05:30.000Z"), $lt: ISODate("2018-02-24T20:05:30.000Z") } } }, { $addFields: { offduration: { $divide: [ { $subtract: ["$RECEIVEDDATE", "$CREATE_DATE"] }, 3600000 ] } } }, // 第一步:分组计算平均时长,同时保存分组内所有文档的_id { "$group": { _id: { SWITCHID: "$SWITCHID", STATUS: "$STATUS" }, avgduration: { $avg: "$offduration" }, docIds: { $push: "$_id" } } }, // 第二步:关联原始集合,获取所有相关文档的完整字段 { $lookup: { from: "lights", localField: "docIds", foreignField: "_id", as: "originalDocs" } } ])
小提醒
- 用
$first/$last的时候,一定要确保分组内的目标字段值是一致的,不然会随机取第一个或最后一个值,可能不是你想要的结果。 - 如果你的集合数据量很大,
$lookup可能会有点影响性能,优先选方案一(只要字段值在分组内是固定的)。
内容的提问来源于stack exchange,提问作者Naresh G
相关产品推荐
相关产品推荐

