MongoDB订单集合关联商品查询聚合优化及索引创建方案咨询
MongoDB 关联购买商品查询优化方案
一、聚合管道本身优化
- 合并前置匹配阶段,减少初始扫描量:将原来分散的2次
$match合并为聚合的第一个阶段,利用MongoDB的查询优化规则让匹配条件优先命中索引,同时避免中间阶段生成冗余数据。原来的$addFields计算订单商品数和sku列表可以直接整合到匹配条件中,省略该阶段开销。 - 调整过滤顺序降低后续计算量:将排除目标sku的
$match调整到$sort之前,先过滤掉不需要统计的目标sku数据,再执行排序,减少排序操作的数据集大小。 - 精简中间传输字段:新增
$project阶段仅保留后续计算需要的products字段,避免携带订单其他冗余字段参与计算,降低内存和IO开销。
优化后聚合管道代码如下:
[ // 合并所有前置过滤条件,优先命中索引 { '$match': { 'status': { '$nin': ['CANCELLED', 'CHECK_OUT'] }, 'products.sku': '3516215049767', // 直接匹配数组包含目标sku,无需$elemMatch '$expr': { '$gte': [ { '$size': '$products' }, 2 ] } // 直接判断商品数≥2,无需提前新增字段 } }, // 仅保留需要的products字段,减少数据传输开销 { '$project': { 'products.sku': 1, '_id': 0 } }, // 展开sku数组 { '$unwind': '$products' }, // 分组统计sku出现次数 { '$group': { '_id': '$products.sku', 'count': { '$sum': 1 } } }, // 先排除目标sku,再排序减少数据量 { '$match': { '_id': { '$ne': '3516215049767' } } }, { '$sort': { 'count': -1 } }, { '$limit': 4 } ]
二、新增索引建议
- 新增复合多键索引:针对前置匹配的两个核心过滤字段
status和products.sku,建立如下索引:
db.Orders.createIndex({ status: 1, "products.sku": 1 })
索引说明:该索引为多键复合索引,第一前缀
status可以快速过滤掉取消、未结账的订单,第二键products.sku会为订单下所有商品sku单独建立索引条目,可以直接定位到包含目标sku的订单,不需要全表扫描所有订单。优化后查询的扫描文档数会直接降低到符合过滤条件的订单量级,扫描/返回比值会回到合理范围。
内容的提问来源于stack exchange,提问作者Florian Burel
相关产品推荐
相关产品推荐

