如何为Mongoose实现多条件过滤?游戏商店需新增平台系统过滤
可行实现方案解答
核心结论
不需要必须将platform和system加入tags数组,更推荐独立维护维度+扩展过滤逻辑的方案,既保留数据语义清晰性,又便于后续功能扩展。
方案一:独立扩展过滤逻辑(推荐)
platform(发行平台,如Steam)和system(运行系统,如PC)属于和tags/genres平行的分类维度,单独处理过滤逻辑更合理,具体修改如下:
1. 修改API Controller代码
async get(req, res) { try { const page = parseInt(req.query.page) - 1 || 0; const limit = parseInt(req.query.limit) || 5; const search = req.query.search || ''; let sort = req.query.sort || "top"; let tags = req.query.tags || 'all'; // 新增平台和系统的查询参数 let platforms = req.query.platforms || 'all'; let systems = req.query.systems || 'all'; // 用distinct高效获取所有可选维度值(替代原全查循环的低效写法) const [tagsOpt, platformOpt, systemOpt] = await Promise.all([ Games.distinct('tags'), Games.distinct('platform'), Games.distinct('system') ]); // 处理各维度参数 tags === 'all' ? (tags = [...tagsOpt]) : (tags = req.query.tags.split(',')); platforms === 'all' ? (platforms = [...platformOpt]) : (platforms = req.query.platforms.split(',')); systems === 'all' ? (systems = [...systemOpt]) : (systems = req.query.systems.split(',')); // 处理排序逻辑(修复原代码的赋值错误) req.query.sort ? (sort = req.query.sort.split(',')) : (sort = [sort]); let sortBy = {}; if (sort[1]) { sortBy[sort[0]] = sort[1] === 'asc' ? 1 : -1; } else { sortBy['top'] = -1; } // 构建复合查询条件 const query = { title: { $regex: search, $options: 'i' }, tags: { $in: [...tags] } }; // 添加平台过滤 if (platforms.length > 0 && platforms !== 'all') { query.platform = { $in: [...platforms] }; } // 添加系统过滤 if (systems.length > 0 && systems !== 'all') { query.system = { $in: [...systems] }; } // 查询数据 const gamesData = await Games.find(query) .sort(sortBy) .skip(page * limit) .limit(limit); const total = await Games.countDocuments(query); const response = { error: false, total, page: page + 1, limit, tags: tagsOpt, platforms: platformOpt, // 返回可选平台列表给前端 systems: systemOpt, // 返回可选系统列表给前端 gamesData }; res.status(200).json(response); } catch (error) { console.log(error); res.status(400).json({ message: 'Ошибка получения' }) } }
2. 代码优化说明
- 用
Promise.all结合distinct批量获取所有可选维度值,替代原全量查询游戏再循环的低效逻辑,大幅提升性能 - 修复了原排序逻辑中的赋值错误(
sortBy[sort[0] = sort[1]]是错误写法,改为正确的键值对赋值) - 新增返回
platforms和systems可选列表,方便前端渲染筛选器选项 - 各过滤维度独立可控,后续新增其他维度(如价格区间)时可快速扩展
方案二:合并到tags数组(不推荐)
如果想复用现有tags的过滤逻辑,可以在保存游戏数据时,将platform的值和system数组的元素批量加入到tags数组中(例如:game.tags.push(game.platform, ...game.system)),这样无需修改过滤逻辑即可实现平台/系统的筛选。
但该方案存在明显缺点:
- 数据语义混淆:tags原本是标签维度,混入平台/系统后难以区分,后续维护(如修改平台名称)容易出错
- 无法单独统计或展示平台/系统维度的信息,限制后续功能扩展
内容的提问来源于stack exchange,提问作者Slow Storm
相关产品推荐
相关产品推荐

