MongoDB百万级数据中查询指定productId的最大at时间
MongoDB百万级数据下指定productId的最大action time高效查询方案
需求
从百万级数据量的MongoDB集合中,查询指定productId列表内每个产品的最大at(action time)值,要求方案稳定高效。
示例数据
指定查询productId为125或126,集合数据如下:
[ { "_id": ObjectId("..."), "at": "2022-03-25 05:00:00", "productId": 125 }, { "_id": ObjectId("..."), "at": "2022-03-25 04:00:00", "productId": 125 }, { "_id": ObjectId("..."), "at": "2022-03-24 12:00:00", "productId": 126 }, { "_id": ObjectId("..."), "at": "2022-03-25 08:00:00", "productId": 127 } ]
预期输出
[ { "_id": ObjectId("..."), "productId": 125, "at": "2022-03-25 05:00:00" }, { "_id": ObjectId("..."), "productId": 126, "at": "2022-03-24 12:00:00" } ]
高效解决方案
1. 创建复合索引(核心优化)
针对百万级数据,必须创建复合索引避免全表扫描,大幅提升查询速度:
db.collection.createIndex({ productId: 1, at: -1 })
- 索引逻辑:先按
productId升序分组,再按at降序排列,让MongoDB快速定位目标数据并直接获取最大时间值。
2. 聚合查询实现
根据需求选择以下两种方式:
方式一:仅获取productId与最大at值
如果只需要产品ID和对应最大时间,此方案更轻量:
db.collection.aggregate([ // 过滤目标productId,缩小数据集 { $match: { productId: { $in: [125, 126] } } }, // 按productId分组,提取最大at值 { $group: { _id: "$productId", productId: { $first: "$productId" }, maxAt: { $max: "$at" } } }, // 调整输出字段格式 { $project: { _id: 0, productId: 1, at: "$maxAt" } } ])
方式二:获取最大at对应的完整文档
如果需要包含原文档的_id等其他字段,用此方案:
db.collection.aggregate([ { $match: { productId: { $in: [125, 126] } } }, // 利用索引按productId分组、at倒序排序,无需额外内存排序 { $sort: { productId: 1, at: -1 } }, // 取每组第一条(即at最大的文档) { $group: { _id: "$productId", doc: { $first: "$$ROOT" } } }, // 还原文档结构 { $replaceRoot: { newRoot: "$doc" } } ])
注意事项
- 确保
at字段格式为可排序的字符串(如示例的YYYY-MM-DD HH:MM:SS),或直接存储为ISODate类型,避免排序逻辑错误。 - 若
$in中的productId数量极大,可分批查询减少单次内存占用。
内容的提问来源于stack exchange,提问作者Mehmet Serkan Ekinci
相关产品推荐
相关产品推荐

