如何高效计算同一MongoDB集合下两个cursor的差集:cursor1独有元素
MongoDB两个cursor求差集的实现方案
方案1:服务端聚合计算(优先推荐,性能最优)
该方案完全在MongoDB服务端执行,不需要拉取全量数据到客户端,支持大数据量场景:
const difference = collection1.aggregate([ // 匹配cursor1的查询条件,拿到第一个子集的全部文档 { $match: ...condition 1... }, // 关联匹配第二个子集的内容 { $lookup: { // 如果是同一个集合的两个cursor,此处填当前集合的名称即可 from: "collection2", let: { refIndex: "$collection1index" }, pipeline: [ { $match: { $expr: { $eq: ["$collection1index", "$$refIndex"] }, // 填入cursor2的查询条件 ...condition 2... }}, { $limit: 1 } ], as: "matched_in_cursor2" } }, // 过滤掉在第二个子集中存在的文档,剩余就是仅在cursor1中存在的差集 { $match: { matched_in_cursor2: { $size: 0 } } }, // 可选:删除临时生成的匹配标记字段 { $unset: "matched_in_cursor2" } ])
方案2:客户端遍历计算(仅适合千级以内的小数据量场景)
如果数据集非常小,可以直接在客户端将cursor转为内存数据做对比:
// 先提取cursor2的所有关联字段存入Set,用于O(1)效率的存在性判断 const cursor2IndexSet = new Set( await cursor2.map(item => item.collection1index).toArray() ) const difference = [] // 遍历cursor1筛选差集 await cursor1.forEach(doc => { if (!cursor2IndexSet.has(doc.collection1index)) { difference.push(doc) } })
注意事项
- 方案2需要把两个cursor的全量结果加载到客户端内存,数据量超过万级时会有明显的性能损耗甚至内存溢出风险,非必要不推荐使用
- 判断文档归属的依据字段可以替换为
_id等全局唯一字段,只要能唯一标识文档即可 - 数据量较大时建议给关联字段、查询条件涉及的字段添加索引,进一步提升查询效率
内容的提问来源于stack exchange,提问作者haton
相关产品推荐
相关产品推荐

