如何编写MongoDB查询找出传入数组中不在集合内的缺失元素
问题场景
- 传入待匹配数组:
animals = ['cat','mat','rat'] - 目标集合现有文档仅包含
animal字段值为cat、mat的两条记录,结构如下:
[ { _id: ObjectId, animal: "cat" }, { _id: ObjectId, animal: "mat" } ]
- 预期需求:返回传入数组中不存在于集合内的元素,即示例中的
rat - 误区说明:以下两种
$nin写法无法实现需求:
// 错误写法1 db.collection.find({'animal':{$nin:animals}}) // 错误写法2 db.collection.find({'animal':{$nin:['cat','mat','rat']}})
这类写法的逻辑是筛选集合内animal字段不在传入数组中的文档,本质是对集合已有数据做过滤,当前集合所有文档的animal值都在传入数组中,执行后只会返回空结果,和「找传入数组中未被集合存储的元素」的逻辑完全相反。
正确查询写法
MongoDB原生查询默认以集合内文档为筛选对象,要计算传入参数和集合存储值的差集,需要通过聚合管道实现:
db.collection.aggregate([ // 筛选出集合中属于传入数组范围内的animal值 { $match: { animal: { $in: ['cat','mat','rat'] } } }, // 对已存在的animal值去重汇总 { $group: { _id: null, existValues: { $addToSet: '$animal' } }}, // 计算传入数组和已存在值的差集,得到缺失的元素 { $project: { _id: 0, missingElements: { $setDifference: [['cat','mat','rat'], '$existValues'] } }} ])
执行上述语句后返回结果如下,正好符合预期:
{ "missingElements" : [ "rat" ] }
如果传入数组是动态变量,只需要将语句中两处写死的数组替换为对应变量即可。
内容的提问来源于stack exchange,提问作者Sugumar Venkatesan
相关产品推荐
相关产品推荐

