MongoDB分组查询性能优化及结果格式等技术问询
问题背景与需求
我有3个用于存储datamodel(产品)信息的集合:
datamodel:每个文档对应一个唯一datamodelrelease:每个文档对应平台、版本、datamodel的组合datatree:每个文档对应datamodel中的一个节点,字段包括id(xpath,每个datamodel的节点id唯一)、nodehash(节点属性哈希值)、base-type(节点类型)
所有集合通过mod_id关联。
需求:对比平台BXR的1.3.0和1.8.1两个版本,获取所有datamodel的节点及叶子节点的新增、删除、修改统计数据。
我将需求拆分为两个查询:
- 第一个查询筛选出两个版本间有变化的datamodel的
mod_id; - 第二个查询基于这些
mod_id,按以下逻辑统计:- 拉取两个版本相关的节点,分别放入
fromMod(1.3.0版本)和toMod(1.8.1版本)桶中; - 对比节点:仅在
fromMod则为删除,仅在toMod则为新增,id都存在但nodehash不同则为修改; - 按datamodel分组统计各类节点数量。
- 拉取两个版本相关的节点,分别放入
已实现第二个查询,但存在以下疑问:
- 查询耗时约22秒,是否有更优查询方式?
- 如何将结果转换为预期格式?
- 是用单查询完成需求更好,还是拆分为两个查询更合适?
解决方案
1. 优化查询耗时
- 索引优化:给
release集合的platform、version、mod_id建立复合索引,快速定位目标版本关联的mod_id;给datatree集合的mod_id、id、nodehash建立复合索引,加速节点匹配与哈希对比操作。 - 提前过滤数据:先通过
release集合精准筛选出BXR平台1.3.0和1.8.1版本对应的mod_id列表,再以此为过滤条件查询datatree,避免全集合扫描。 - 精简返回字段:查询
datatree时仅返回mod_id、id、nodehash、base-type这些必要字段,减少数据传输与处理的开销。
2. 转换为预期格式
假设预期格式是按datamodel分组,包含总节点和叶子节点的新增/删除/修改统计,可以在聚合查询末尾添加以下阶段来重塑结构:
{ $group: { _id: "$mod_id", total_nodes: { $mergeObjects: { added: { $sum: "$total.added" }, removed: { $sum: "$total.removed" }, modified: { $sum: "$total.modified" } } }, leaf_nodes: { $mergeObjects: { added: { $sum: "$leaf.added" }, removed: { $sum: "$leaf.removed" }, modified: { $sum: "$leaf.modified" } } } } }, { $project: { _id: 0, datamodel_id: "$_id", total_nodes: 1, leaf_nodes: 1 } }
如果需要补充datamodel的名称等信息,可加入$lookup阶段关联datamodel集合,整合对应字段。
3. 单查询 vs 拆分查询
拆分查询更优:
- 第一个查询仅筛选有变化的
mod_id,数据量小、速度快;第二个查询只针对这些有变化的mod_id处理节点数据,避免对无变化的datamodel做无效对比,大幅降低计算量。 - 若合并为单查询,聚合逻辑会变得复杂,且会扫描所有datamodel的节点数据,耗时更长,后续维护成本也更高。
内容的提问来源于stack exchange,提问作者Udhayha Karthik
相关产品推荐
相关产品推荐

