MongoDB聚合查询:关联items与激活状态tax_schema匹配税分类
正确关联MongoDB集合获取对应税类信息的聚合查询
集合数据
items集合
[ {'item_code':'A001', 'tax_category_code':'T001', 'price': 98}, {'item_code':'A002', 'tax_category_code':'T002', 'price': 39}, {'item_code':'A003', 'tax_category_code':'T001', 'price': 77}, {'item_code':'A004', 'tax_category_code':'T003', 'price': 52} ]
tax_schema集合
[ {'status':'active', 'categories': [ {'tax_category_code':'T001', 'priority': 1, 'percentage': 0.1}, {'tax_category_code':'T002', 'priority': 3, 'percentage': 0.5}, {'tax_category_code':'T003', 'priority': 2, 'percentage': 0.87} ], 'date': '2022-11-24T00:00:00-05:00'}, {'status':'inactive', 'categories': [ {'tax_category_code':'T001', 'priority': 0, 'percentage': 0.08}, {'tax_category_code':'T002', 'priority': 2, 'percentage': 0.42}, {'tax_category_code':'T003', 'priority': 4, 'percentage': 0.74} ], 'date': '2022-06-06T00:00:00-05:00'}, {'status':'inactive', 'categories': [ {'tax_category_code':'T001', 'priority': 0, 'percentage': 0.05}, {'tax_category_code':'T002', 'priority': 0, 'percentage': 0.41}, {'tax_category_code':'T003', 'priority': 0, 'percentage': 0.72} ], 'date': '2022-03-31T00:00:00-05:00'} ]
需求说明
获取所有items数据,关联status为active的tax_schema集合,根据tax_category_code匹配对应分类,返回item原有字段加上匹配到的priority和percentage字段,期望结果如下:
[ {'item_code':'A001', 'tax_category_code':'T001', 'price': 98, 'priority': 1, 'percentage': 0.1}, {'item_code':'A002', 'tax_category_code':'T002', 'price': 39, 'priority': 3, 'percentage': 0.5}, {'item_code':'A003', 'tax_category_code':'T001', 'price': 77, 'priority': 1, 'percentage': 0.1}, {'item_code':'A004', 'tax_category_code':'T003', 'price': 52, 'priority': 2, 'percentage': 0.87} ]
(注:原期望结果格式存在语法问题,此处调整为MongoDB合法的键值对格式)
原查询问题
原聚合查询未过滤status: active的tax_schema文档,且lookup仅匹配包含目标tax_category_code的文档,导致返回所有符合条件的tax_schema(包括inactive状态);后续取第一个文档的categories数组时,拿到的是该文档下所有分类,而非当前item匹配的单个分类。
正确聚合查询语句
db.getCollection('items').aggregate([ { $lookup: { from: 'tax_schema', let: { item_tax_code: "$tax_category_code" }, pipeline: [ // 筛选active状态的税配置文档 { $match: { status: "active" } }, // 拆分数组,将每个分类转为独立文档 { $unwind: "$categories" }, // 匹配当前item的税分类代码 { $match: { $expr: { $eq: ["$categories.tax_category_code", "$$item_tax_code"] } } }, // 仅保留需要的字段 { $project: { _id: 0, priority: "$categories.priority", percentage: "$categories.percentage" } } ], as: "tax_info" } }, // 展开匹配到的税信息数组(每个item仅匹配一条结果) { $unwind: "$tax_info" }, // 重组输出字段结构 { $project: { _id: 0, item_code: 1, tax_category_code: 1, price: 1, priority: "$tax_info.priority", percentage: "$tax_info.percentage" } } ])
语句说明
- 管道模式$lookup:
- 用
let定义当前item的税分类代码变量,方便内部管道引用 - 先过滤active状态的tax_schema,减少无效匹配
- 通过
$unwind拆分categories数组,让每个分类成为可单独匹配的单元 - 用
$expr实现跨集合的字段匹配,精准定位当前item对应的税分类 - 仅保留需要的priority和percentage字段,降低数据传输量
- 用
- $unwind:展开匹配到的tax_info数组,确保每个item对应一条税信息
- $project:重组输出字段,将税信息字段直接合并到item文档中,得到符合需求的结构
内容的提问来源于stack exchange,提问作者Mario Santiago Pérez Morán
相关产品推荐
相关产品推荐

