Next JS + MongoDB搜索功能异常排查请求
搜索功能失效排查:Next.js MongoDB API返回所有数据而非匹配结果
问题描述
我在开发Next.js API的搜索功能,该API存储燃油价格、加油站名称等数据。预期请求携带keyword参数时,仅返回匹配关键词的结果,但实际返回所有数据,和MongoDB普通find()函数的行为一致。
相关代码
ApiFeatures类代码
class ApiFeatures { constructor(query, queryStr) { this.query = query; this.queryStr = queryStr; } search() { const keyword = this.queryStr.keyword ? { $or: [ // 疑似问题点 { name: { $regex: this.queryStr.keyword, $options: "i", }, }, { email: { $regex: this.queryStr.keyword, $options: "i", }, }, { // 怀疑此处字段名有误 petrolPumpName: { $regex: this.queryStr.keyword, $options: "i", }, }, ], } : {}; this.query = this.query.find({ ...keyword }); return this; } }
Next.js API处理函数
const handler = catchAsyncErrors(async (req, res) => { const apiFeature = new ApiFeatures( User.find().select("-role -verified"), req.query ).search(); const users = await apiFeature.query; if (users.length === 0) { return res.status(404).json("No User Found"); } return res.status(200).json(users); }); export default connectToMongo(isAuthenticated(catchAsyncErrors(handler)));
失效现象(燃油API场景)
请求URL:http://localhost.com/fuelStation?keyword=AbcfuelStation
返回数据:
{ "rate": 50, "quantity": 100, "amount": 5000, "fuelStationName": "Abc fuel Station" }, { "rate": 50, "quantity": 100, "amount": 5000, "fuelStationName": "XYZ" }
不符合预期的是,未匹配关键词的XYZ加油站也被返回。
原因分析
- 字段名不匹配:
代码中搜索燃油站名称用的是petrolPumpName,但实际数据中的字段是fuelStationName,导致该搜索条件完全失效。同时燃油站集合不存在name/email字段,$or中的这两个条件也无法匹配任何数据,最终搜索条件等价于空对象,返回所有数据。 req.query.keyword未正确获取:
若请求参数名拼写错误(如大小写不匹配)、中间件修改了req.query导致keyword丢失,或关键词为空字符串,都会使keyword变量变为空对象,触发find({})返回所有数据。- 跨集合搜索逻辑混乱:
同一个ApiFeatures类被用于用户和燃油站两个不同集合,搜索字段包含了双方的专属字段,导致在单个集合中查询时,多数条件无效,降低搜索准确性。
解决方法
1. 修正字段名匹配
将ApiFeatures.search()中的petrolPumpName改为实际字段名fuelStationName:
{ fuelStationName: { $regex: this.queryStr.keyword, $options: "i", }, }
2. 优化跨集合搜索逻辑
让search方法支持自定义搜索字段,避免无效条件:
class ApiFeatures { constructor(query, queryStr) { this.query = query; this.queryStr = queryStr; } search(searchFields = ["name", "email"]) { if (!this.queryStr.keyword?.trim()) return this; const keywordRegex = { $regex: this.queryStr.keyword.trim(), $options: "i", }; const orConditions = searchFields.map(field => ({ [field]: keywordRegex })); this.query = this.query.find({ $or: orConditions }); return this; } } // 用户API调用 const apiFeature = new ApiFeatures(User.find().select("-role -verified"), req.query) .search(["name", "email"]); // 燃油站API调用 const apiFeature = new ApiFeatures(FuelStation.find(), req.query) .search(["fuelStationName"]);
3. 排查参数获取问题
在API handler中添加日志,确认req.query.keyword的值:
const handler = catchAsyncErrors(async (req, res) => { console.log("Received keyword:", req.query.keyword); // 剩余代码不变 });
若日志显示undefined,需:
- 检查请求URL的参数名是否为
keyword(大小写敏感); - 确认
isAuthenticated等中间件未修改或删除req.query中的keyword参数; - 验证Next.js默认的URL参数解析是否正常(默认配置支持)。
4. 处理空关键词场景
添加空值校验,避免空关键词触发全量返回:
search() { const keyword = this.queryStr.keyword?.trim() ? { $or: [ { name: { $regex: this.queryStr.keyword.trim(), $options: "i" } }, { email: { $regex: this.queryStr.keyword.trim(), $options: "i" } }, { fuelStationName: { $regex: this.queryStr.keyword.trim(), $options: "i" } }, ], } : {}; this.query = this.query.find({ ...keyword }); return this; }
内容的提问来源于stack exchange,提问作者Raghav Patel
相关产品推荐
相关产品推荐

