如何通过MongoDB聚合查询获取多文档refId字段的交集数据
MongoDB聚合查询:获取多文档refId数组的交集
现有查询与输出
当前通过MongoDB聚合查询,使用$in匹配指定email数组,返回包含email和refId数组的文档列表,原查询及输出如下:
原聚合查询
const aggregateQuery = [ { '$match': { 'email': { '$in': ['abc@testmail.com', 'xyz@testmail.com', 'qwe@testmail.com'] }, 'deleted': false } }, { /* 其他业务逻辑 */ }, { '$project': { 'email': 1, 'refId': '$dataArray._id' } } ];
当前输出
[ { _id: 't1', email: 'abc@testmail.com', refId: ['ref1', 'ref2', 'ref3','ref4','ref5'] }, { _id: 't2', email: 'xyz@testmail.com', refId: ['ref1', 'ref2','ref5','ref82'] }, { _id: 't3', email: 'qwe@testmail.com', refId: ['ref2', 'ref5','ref77'] } ]
需求说明
需要修改上述聚合查询,获取所有返回文档中refId数组的交集(命名为Common_RefIds),且适配任意数量的输入文档,期望输出如下:
期望输出
[ { Common_RefIds: ['ref2', 'ref5'] } ]
修改后的聚合查询
可以通过以下聚合阶段实现数组交集计算,适配任意数量的输入文档:
const aggregateQuery = [ { '$match': { 'email': { '$in': ['abc@testmail.com', 'xyz@testmail.com', 'qwe@testmail.com'] }, 'deleted': false } }, { /* 保留原有的其他业务逻辑 */ }, { '$project': { 'refId': '$dataArray._id' } }, // 仅保留refId数组,减少后续计算数据量 { '$group': { '_id': null, 'allRefIds': { '$push': '$refId' } } }, // 将所有refId数组收集到一个数组中 { '$project': { '_id': 0, 'Common_RefIds': { '$reduce': { 'input': '$allRefIds', 'initialValue': { '$arrayElemAt': ['$allRefIds', 0] }, // 以第一个数组为初始交集 'in': { '$filter': { 'input': '$$value', 'cond': { '$in': ['$$this', '$$current'] } // 筛选出当前数组与累计交集的共同元素 } } } } } } ];
逻辑说明
$project阶段:仅保留refId字段,减少后续处理的数据量。$group阶段:将所有文档的refId数组收集到allRefIds数组中,_id: null表示将所有文档合并为一组。$project+$reduce阶段:- 用
$reduce遍历allRefIds数组,以第一个数组作为初始交集值。 - 每一步通过
$filter筛选出当前数组与累计交集的共同元素,逐步缩小范围,最终得到所有数组的公共元素。
- 用
内容的提问来源于stack exchange,提问作者Vishal Gupta
相关产品推荐
相关产品推荐

