如何在Mongoose中实现葡萄酒查询的年份/价格过滤且默认返回全量数据?
问题分析与优化方案
你的需求是为葡萄酒API添加年份、价格过滤功能,同时保证未指定这些参数时不会返回空数组,现有实现尚未完成目标逻辑,且当前写法并非最优方案,下面是具体分析和优化代码:
现有代码的不足
- 未实现年份、价格的过滤逻辑,相关代码处于注释状态
- 链式调用
.where()的方式不够灵活:如果直接启用年份过滤的注释代码,当year参数未指定时,parseInt(year)会得到NaN,.equals(NaN)会导致查询不到任何数据,直接返回空数组,违反需求 - 参数类型处理不严谨:
page和limit从req.query获取的是字符串,后续计算skip时才转换,容易出现隐式类型转换错误
优化后的实现代码
getWines: async (req, res) => { try { const types = ['red', 'white']; // 提前转换参数类型,默认值设置更严谨 const { limit = 10, page = 1, search = '', type = 'all', year, price } = req.query; const pageNum = parseInt(page); const limitNum = parseInt(limit); // 校验页码有效性 if (pageNum <= 0 || isNaN(pageNum)) { return res.status(400).json({ error: 'Invalid page number' }); } if (limitNum <= 0 || isNaN(limitNum)) { return res.status(400).json({ error: 'Invalid limit number' }); } // 动态构建查询条件,仅在参数有效时添加过滤规则 const query = { name: { $regex: search, $options: 'i' } }; // 处理类型过滤 if (type !== 'all') { query.type = type; } else { query.type = { $in: types }; } // 处理年份过滤:仅当year存在且为有效数字时添加 if (year) { const yearNum = parseInt(year); if (!isNaN(yearNum)) { query.year = yearNum; } } // 处理价格过滤:仅当price存在且为有效数字时添加 if (price) { const priceNum = parseInt(price); if (!isNaN(priceNum)) { query.price = priceNum; } } // 执行查询 const wines = await Wine.find(query) .limit(limitNum) .skip((pageNum - 1) * limitNum); res.json(wines); } catch (error) { console.error(error); res.status(500).json({ error: 'Internal server error' }); } }
优化点说明
- 动态构建查询对象:通过
query对象按需添加过滤条件,避免了链式调用在参数缺失时的错误逻辑,保证未指定年份/价格时不会添加无效过滤,自然不会返回空数组 - 参数提前校验与转换:提前将
page、limit、year、price转换为数字并校验有效性,避免后续计算和查询出错 - 更严谨的错误处理:对无效参数返回400状态码,服务器错误返回500状态码,符合RESTful规范
- 逻辑更清晰:将不同过滤规则拆分到独立的判断块,代码可读性更高,后续扩展其他过滤条件(比如价格范围、产区)也更方便
需求验证
- 访问
http://localhost:1234/api/wine?year=2010:query中会包含year: 2010,返回2010年的葡萄酒 - 访问
http://localhost:1234/api/wine:query仅包含名称模糊查询和类型全匹配,返回限制10条的全部葡萄酒 - 未指定年份/价格时,不会添加对应过滤条件,只要数据库有数据就不会返回空数组
内容的提问来源于stack exchange,提问作者mongu
相关产品推荐
相关产品推荐

