基于MongoDB Atlas开发REST API时findOne查询已存在文档返回null问题
问题根因
你代码的核心错误是对Mongoose findOne 方法的回调参数顺序理解有误:Mongoose所有异步查询方法的回调函数,第一个参数永远是错误对象,第二个参数才是查询返回的结果数据。
你现在写的Tea.findOne({name:req.body.name},(data) => { ... })里,回调仅接收了第一个参数,这个参数实际是错误对象,没有报错的情况下默认值为null,所以你打印的data永远是null,自然每次都会走新增逻辑。
修复代码
回调写法修复
// POST '/tea' const newTea = (req, res) => { // 检查数据库中是否已存在对应名称的茶品 Tea.findOne({name:req.body.name},(err, data) => { // 优先处理查询错误 if(err) return res.json({Error: err}); console.log(`req.body.name的值为: ${req.body.name}`); console.log(`查询返回的data值为: ${data}`); // 茶品不存在则执行新增 if (data === null) { // 基于Tea模型和请求参数创建新的茶品对象 const newTea = new Tea({ name:req.body.name, image: req.body.image, // 暂为占位字段 description: req.body.description, keywords: req.body.keywords, origin: req.body.origin, brew_time: req.body.brew_time, temperature: req.body.temperature, }) // 将对象存入数据库 newTea.save((err, data)=>{ if(err) return res.json({Error: err}); return res.json(data); }) // 茶品已存在则返回提示 } else { return res.json({message:`名称为${data.name}的茶品已存在`}); } }) };
更推荐的async/await写法(逻辑更清晰,避免回调嵌套)
// POST '/tea' const newTea = async (req, res) => { try { // 查询是否存在同名茶品 const existTea = await Tea.findOne({ name: req.body.name }); if (existTea) { return res.json({ message: `名称为${existTea.name}的茶品已存在` }); } // 不存在则执行新增 const newTea = new Tea(req.body); const savedTea = await newTea.save(); return res.json(savedTea); } catch (err) { return res.json({ Error: err }); } };
额外优化建议
为了避免并发请求下同时查询都判定不存在、重复写入的问题,建议在Tea模型的name字段上添加唯一索引,从数据库层面保证数据唯一性:
// 在Tea模型定义中添加配置 const teaSchema = new mongoose.Schema({ name: { type: String, required: true, unique: true // 唯一索引配置 }, // 其余字段定义... })
内容的提问来源于stack exchange,提问作者lbarqueira
相关产品推荐
相关产品推荐

