如何在Mongoose聚合函数中实现WHERE IN子句
筛选同时包含多个分类ID的Mongoose文档
问题场景
现有两个Mongoose Product文档,需要筛选出同时包含分类ID 62bacb137e6e0b6ac850b9ce 和 63a7b5bb333394043fdca923 的文档(即文档的category数组必须同时包含这两个ID)。之前尝试的聚合代码未达到预期效果。
错误的聚合代码示例:
const product = await Product.aggregate([ { $match: { $text: { $search: `\"${searchText}\"` }, }, }, { $addFields: { root: "$$ROOT", }, }, { $project: { name: "$root.name", category: { $filter: { input: "$root.category", as: "category", cond: { $in: ["62bacb137e6e0b6ac850b9ce" , "63a7b5bb333394043fdca923"] }, }, }, avgRating: { $floor: { $avg: "$ratings.star" }, }, price: "$root.price", slug: "$root.slug", images: "$root.images", color: "$root.color", description: "$root.description", ratings: "$root.ratings", sold: "$root.sold", }, }, ]);
错误原因
这段代码的问题在于:
$filter的作用是过滤数组内的元素,而非筛选整个文档——即使category数组被过滤,不符合条件的文档依然会被保留。$in的语法使用错误,正确格式应为{ $in: [ <待匹配值>, <数组> ] },参数顺序写反,且$in无法实现"同时包含多个值"的逻辑。
正确实现方法
方法一:使用$match+$all(推荐,性能最优)
直接在聚合的$match阶段用$all运算符筛选文档,$all会匹配数组中同时包含所有指定元素的文档,且能利用category字段的索引提升查询效率。
// 定义需要匹配的分类ID数组 const targetCategories = [ "62bacb137e6e0b6ac850b9ce", "63a7b5bb333394043fdca923" ]; const products = await Product.aggregate([ { $match: { $text: { $search: `\"${searchText}\"` }, // 核心:用$all匹配同时包含所有目标分类ID的文档 category: { $all: targetCategories } } }, { $project: { name: 1, category: 1, avgRating: { $floor: { $avg: "$ratings.star" } }, price: 1, slug: 1, images: 1, color: 1, description: 1, ratings: 1, sold: 1 } } ]);
方法二:后续阶段过滤(仅特殊场景使用)
如果因业务限制无法在$match阶段提前过滤,可以在聚合中间阶段通过集合交集判断文档是否符合条件:
const targetCategories = [ "62bacb137e6e0b6ac850b9ce", "63a7b5bb333394043fdca923" ]; const products = await Product.aggregate([ { $match: { $text: { $search: `\"${searchText}\"` } } }, { $addFields: { // 计算当前文档category与目标数组的交集长度,判断是否等于目标数组长度 hasAllCategories: { $eq: [ { $size: { $setIntersection: ["$category", targetCategories] } }, targetCategories.length ] } } }, // 仅保留符合条件的文档 { $match: { hasAllCategories: true } }, { $project: { name: 1, category: 1, avgRating: { $floor: { $avg: "$ratings.star" } }, price: 1, slug: 1, images: 1, color: 1, description: 1, ratings: 1, sold: 1, hasAllCategories: 0 // 移除临时字段 } } ]);
内容的提问来源于stack exchange,提问作者desh
相关产品推荐
相关产品推荐

