You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongo聚合查询优化:不使用$expr实现Lookup内数组匹配

解决MongoDB聚合中避免使用$expr实现多对多关系的成本汇总

你的问题根源在于:$lookup子管道里的普通$match条件不能直接引用let定义的变量,必须用$expr才能访问$$resources_ids,但$expr会让查询跳过索引,拖慢性能。

原来的写法是先按rule_id分组得到资源ID数组,再通过子管道匹配数组内的资源,这种逻辑绕不开$expr,但完全可以换一种思路优化:

优化方案(无需$expr,充分利用索引)

调整聚合顺序,先关联成本数据再分组汇总:

db.collection.aggregate([
  // 用传统lookup关联,自动利用cost_data.resource_id索引
  {
    $lookup: {
      from: "cost_data",
      localField: "resource_id",
      foreignField: "resource_id",
      as: "cost_info"
    }
  },
  // 展开成本数据(单个resource对应多条cost时必须,单条可省略)
  { $unwind: "$cost_info" },
  // 按rule_id分组,汇总总成本
  {
    $group: {
      _id: "$rule_id",
      rule_id: { $first: "$rule_id" },
      total_cost: { $sum: "$cost_info.cost" }
    }
  }
])

为什么这个方案可行?

  1. 索引利用:传统$lookup的localField/foreignField匹配逻辑,MongoDB会自动使用cost_data集合上的resource_id索引,比子管道里的$expr+$in快得多。
  2. 逻辑简化:直接把每个规则下的资源成本关联后再聚合,不需要先分组生成资源数组,完全避开了$expr的使用。

补充说明

如果cost_data中每个resource_id只有一条成本记录,可以去掉$unwind阶段,直接在$group里写:

total_cost: { $sum: { $first: "$cost_info.cost" } }

或者直接$sum: "$cost_info.cost",因为单元素数组会自动取值。

内容的提问来源于stack exchange,提问作者madarinho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:01:09