如何在Mongoose/MongoDB中通过关联字段搜索商品?
通过分类字段搜索商品的实现方案
核心思路
由于Product与Category是一对多关联,Product的category字段存储的是分类ID,要实现按分类名称/描述搜索商品,有两种可行思路:要么先筛选出匹配的分类ID,再用ID查询对应商品;要么直接通过MongoDB的关联聚合查询完成匹配。
具体实现
方式一:先查分类ID,再关联商品
在/src/modules/products/products.service.ts的findAll方法中,先调用分类服务获取匹配的分类,再用分类ID查询商品:
async findAll(searchText?: string) { let queryCondition = {}; if (searchText) { // 搜索匹配name或description的分类 const matchedCategories = await this.categoriesService.findAll({ $or: [ { name: new RegExp(searchText, 'i') }, { description: new RegExp(searchText, 'i') } ] }); // 提取匹配分类的ID集合 const targetCategoryIds = matchedCategories.map(category => category._id); // 组合查询条件:商品自身字段匹配 或 所属分类ID在目标集合中 queryCondition = { $or: [ { name: new RegExp(searchText, 'i') }, { price: new RegExp(searchText, 'i') }, { category: { $in: targetCategoryIds } } ] }; } return this.productModel.find(queryCondition); }
依赖注入说明:需要在ProductsService中注入CategoriesService,确保能调用分类查询方法:
constructor( @InjectModel(Product.name) private readonly productModel: Model<Product>, private readonly categoriesService: CategoriesService ) {}
方式二:MongoDB聚合关联查询
直接通过$lookup关联分类集合,一次聚合完成所有匹配逻辑:
async findAll(searchText?: string) { if (!searchText) { return this.productModel.find(); } return this.productModel.aggregate([ // 关联分类集合,获取商品对应的分类信息 { $lookup: { from: 'categories', // 注意这里是MongoDB中的分类集合名称,需与模型对应 localField: 'category', foreignField: '_id', as: 'categoryDetail' } }, // 匹配条件:商品自身字段匹配,或分类的name/description匹配 { $match: { $or: [ { name: new RegExp(searchText, 'i') }, { price: new RegExp(searchText, 'i') }, { 'categoryDetail.name': new RegExp(searchText, 'i') }, { 'categoryDetail.description': new RegExp(searchText, 'i') } ] } }, // 可选:如果不需要返回分类详情,移除该字段 { $unset: 'categoryDetail' } ]); }
方案对比
- 方式一逻辑简单直观,适合数据量较小的场景,便于维护和调试;
- 方式二通过单次聚合查询完成,减少数据库交互次数,适合数据量较大的场景,但需要注意集合名称的准确性。
内容的提问来源于stack exchange,提问作者Hasibur Rahman
相关产品推荐
相关产品推荐

