如何在MongoDB中基于多条件数组实现批量文档匹配查询?
问题
我想知道能不能用$match/$elemMatch匹配符合输入对象条件数组的文档(0个或多个都可以),同时不用逐个查询每个条件项。我觉得$or没法直接用,因为查询条件数量不固定,难道只能动态构建$or查询?
示例数据
db.tshirts.insertMany([ {_id:0, code: "123", label: "Yellow T-Shirt", style: [{ size: "SM", fabric: "cotton"},{ size: "MD", fabric: "bamboo"}]}, {_id:1, code: "456", label: "Blue T-Shirt", style: [{ size: "MD", fabric: "bamboo"},{ size: "LG", fabric: "cotton"}]}, {_id:2, code: "789", label: "Red T-Shirt", style: [{ size: "SM", fabric: "cotton"},{ size: "LG", fabric: "cotton"}]}, {_id:3, code: "321", label: "Green T-Shirt", style: [{ size: "LG", fabric: "bamboo"},{ size: "LG", fabric: "bamboo"}]} ]) // 查询条件数组 var lookup = [ { code: "123", style: { size: "SM" } }, { code: "789", style: { size: "MD" } }, { code: "321", style: { size: "LG" } }, ]
期望输出
[ {_id:0, code: "123", label: "Yellow T-Shirt", style: [{ size: "SM", fabric: "cotton"},{ size: "MD", fabric: "bamboo"}]}, {_id:3, code: "321", label: "Green T-Shirt", style: [{ size: "LG", fabric: "bamboo"},{ size: "LG", fabric: "bamboo"}]} ]
解决方案
方案1:动态构建$or查询
其实动态构建$or是最直接且高效的方案,完全可行。你只需要遍历lookup数组,把每个条件项转换成对应的查询规则,再塞进$or数组里就行:
// 生成查询条件 const query = { $or: lookup.map(item => ({ code: item.code, style: { $elemMatch: item.style } })) }; // 执行查询 db.tshirts.find(query);
这个查询会匹配所有满足「code等于某个lookup项的code,且style数组里至少有一个元素符合对应size条件」的文档,正好能得到你想要的结果。
方案2:聚合管道实现(无需动态构建$or)
如果不想用$or,也可以用聚合管道结合$expr和$anyElementTrue来处理:
db.tshirts.aggregate([ { $match: { $expr: { $anyElementTrue: { $map: { input: lookup, as: 'item', in: { $and: [ { $eq: ['$code', '$$item.code'] }, { $anyElementTrue: { $map: { input: '$style', as: 's', in: { $eq: ['$$s.size', '$$item.style.size'] } } } } ] } } } } } } ]);
逻辑是:遍历lookup数组,对每个文档检查是否存在某个lookup项满足「code相等,且style数组里有元素匹配对应size」,只要有一个符合就会被筛选出来。
补充说明
- 动态
$or方案性能更优,MongoDB可以利用code和style.size的索引(如果创建了的话)加速查询。 - 聚合方案不用动态构建查询,但性能相对差一些,尤其是集合或lookup数组较大时,因为需要逐个文档做计算。
内容的提问来源于stack exchange,提问作者Rob
相关产品推荐
相关产品推荐

