如何从集合每个文档的数组中检索含$max字段的对象?附示例数据
从MongoDB文档数组中提取对应字段最大值的记录
嘿,我猜你是想从每个地点的历史天气数组里,找出某个字段(比如温度、风速)最大值对应的那条记录——你提到的$max应该是指MongoDB的最大值操作符,而不是数组对象里的字段名对吧?下面给你两种实用的解决方案,适配不同的场景:
方案1:经典拆分-分组法(适合需要保留额外聚合信息的场景)
如果除了最大值记录,你还需要同时获取该地点的最高温度数值这类信息,可以用这个流程:
db.weather.aggregate([ // 把history数组拆成单条记录文档 { $unwind: "$history" }, // 按地点分组,计算最高温并保留所有历史记录 { $group: { _id: "$location", maxTemp: { $max: "$history.temp" }, allHistory: { $push: "$history" } } }, // 筛选出对应最高温的那条记录 { $project: { location: "$_id", maxTempRecord: { $first: { $filter: { input: "$allHistory", cond: { $eq: ["$$this.temp", "$maxTemp"] } } } }, _id: 0 } } ])
为啥这么写?
$unwind:把数组拆成独立文档,方便后续分组计算最大值。$group:按地点聚合,算出每个地点的最高温度,同时把所有历史记录存起来备用。$filter+$first:从存好的历史记录里挑出温度等于最高温的那条,$first是防止有多个相同最高温的记录时只取第一条。
方案2:数组内直接遍历(性能更优)
如果你的MongoDB版本在3.4及以上,推荐用$reduce直接在数组里比较,不用拆分数组,速度更快:
db.weather.aggregate([ { $project: { location: 1, maxTempRecord: { $reduce: { input: "$history", initialValue: { temp: -Infinity }, // 初始值设成极低温度,确保第一条记录能替换它 in: { $cond: [ { $gt: ["$$this.temp", "$$value.temp"] }, // 比较当前记录和已有最大值的温度 "$$this", // 当前温度更高,就替换成当前记录 "$$value" // 否则保留原来的最大值记录 ] } } }, _id: 0 } } ])
这个方法的好处:
- 不用拆分数组,避免生成大量中间文档,数据量越大,性能优势越明显。
- 代码更简洁,逻辑直接在数组内部完成。
扩展:换其他字段怎么办?
比如你想找最大风速的记录,只需要把代码里的temp替换成wind_speed就行:
- 把
$$this.temp改成$$this.wind_speed - 把
initialValue: { temp: -Infinity }改成initialValue: { wind_speed: -Infinity }
内容的提问来源于stack exchange,提问作者Ben Lamm
相关产品推荐
相关产品推荐

