如何在MongoDB中高效查询商品及其分类(50万数据集)
高效商品搜索聚合方案
针对你的50万条商品集合需求,我们可以通过单次聚合查询同时返回分页商品列表、去重分类集合和匹配总数,避免多次查询带来的性能损耗。核心思路是先用文本索引过滤匹配文档,再通过$facet并行处理三个分支需求:
完整聚合查询代码
db.products.aggregate([ // 全局执行一次文本匹配,所有子管道复用该结果(仅执行一次文本索引查询,提升效率) {$match: { $text: { $search: "Iphone 11 screen protector" } } }, // 分三个并行分支处理不同需求 {$facet: { // 分支1:统计匹配的总记录数 totalCount: [ {$count: "value"} ], // 分支2:获取分页排序后的商品列表(保留文本匹配评分) productList: [ {$sort: { score: { $meta: "textScore" } }}, {$skip: 0 }, {$limit: 10}, // 按需返回字段,减少数据传输量 {$project: { product_title: 1, category_name: 1, score: { $meta: "textScore" }, _id: 1 // 可添加其他业务需要的字段,如price、stock等 }} ], // 分支3:提取去重的可用分类集合 availableCategories: [ {$group: {_id: "$category_name"}}, // 按分类名去重 {$group: {_id: null, categories: {$push: "$_id"}}}, // 收集为数组 {$project: {_id: 0, categories: 1}} // 整理输出格式 ] }}, // 最后统一输出格式,去除嵌套数组 {$addFields: { totalCount: {$arrayElemAt: ["$totalCount.value", 0]}, availableCategories: {$arrayElemAt: ["$availableCategories.categories", 0]} }} ])
关键优化点说明
- 单次文本查询复用:所有子管道共享初始
$match的结果,避免多次执行开销较高的文本索引查询,这对50万级别的数据集至关重要。 - 高效分类去重:利用
$group对过滤后的文档按category_name去重,结合已有的单键索引,分组操作会更高效。 - 按需字段返回:通过
$project只返回业务需要的字段,减少网络传输和内存占用。 - 分页逻辑保留:沿用你原有的
$sort/$skip/$limit逻辑,确保结果按文本匹配度排序并分页。
查询结果示例
返回的文档结构会清晰包含三个核心部分:
{ "totalCount": 125, // 匹配的总记录数 "productList": [ /* 10条按评分排序的商品文档 */ ], "availableCategories": ["手机配件", "数码周边", /* 其他匹配的分类 */ ] }
内容的提问来源于stack exchange,提问作者Denys Medvediev
相关产品推荐
相关产品推荐

