MongoDB聚合查询查找attribute A缺失v1组件的员工文档
MongoDB聚合查询修正:筛选attribute A下缺失v1组件的员工记录
集合结构示例
单条文档存储结构如下:
{ "_id": { "$oid": "61dde" }, "employee": "Joe", "dateTime": "2022-06-24T01:31:23.41Z", "fileContents": { "inventory": [ { "attribute": "A", "attributeInventory": [ { "atrributeCompId": "v1", }, { "attributeCompId": "v2", } ] }, { "attribute": "B", "attributeInventory": [ { "atrributeCompId": "b1", } ] }, { "attribute": "C", "attributeInventory": [ { "atrributeCompId": "C1", } ] } ] } }
业务规则
- 每位员工的
attribute字段均为必填,每个attribute对应专属的atrributeCompId集合 - 仅
attribute: "A"的条目可关联多个componentId,其中v1、v2为必填值 - 现存大量文档存在v1、v2缺失其一的问题,绝大多数缺失场景为缺少
v1
原查询的核心错误
- 语法错误:
$match是聚合管道阶段,不能作为运算符在$expr表达式内部嵌套使用 - 字段拼写错误:原查询中写的
attrbuteCompId和文档实际字段名不匹配 - 逻辑漏洞:
$unwind后未先筛选attribute: "A"的条目,会把B、C属性的条目纳入匹配,导致结果误判 - 性能问题:最后分组用
_id: null把所有结果塞入单个数组,海量数据场景下会触发BSON 16MB大小限制,且$unwind全量展开数组的性能极差
修正后的聚合查询
以下版本无需$unwind,适合海量数据场景,可配合索引优化查询速度:
db.collection.aggregate([ { $match: { $expr: { $not: [ { $anyElementTrue: { $map: { input: "$fileContents.inventory", as: "invItem", in: { $and: [ { $eq: ["$$invItem.attribute", "A"] }, { $in: [ "v1", "$$invItem.attributeInventory.atrributeCompId" ] } ] } } } } ] } } }, { $project: { _id: 0, employee: 1, dateTime: 1 } } ])
查询逻辑说明
- 直接在数组层面做判断,避免
$unwind全量展开文档带来的性能损耗,若给fileContents.inventory.attribute、fileContents.inventory.attributeInventory.atrributeCompId创建复合索引,查询速度可进一步提升 - 用
$map遍历inventory数组,判断是否存在attribute: "A"且关联v1组件的条目,再通过$not取反,直接得到所有A属性下缺失v1的文档 - 最后投影阶段只返回需要的员工、时间字段,避免加载大体积的
fileContents内容,减少内存占用
注意:示例文档中componentId字段存在拼写不一致问题,部分条目写为正确的
attributeCompId,部分漏写字符为atrributeCompId,如果实际集合字段名统一,替换查询中对应字段名即可。
内容的提问来源于stack exchange,提问作者Aks
相关产品推荐
相关产品推荐

