Node.js中PUT请求无法覆盖MongoDB内容的问题排查
PUT请求无法更新MongoDB数据的排查与解决
问题描述
跟随教程开发时,使用Express+Mongoose编写PUT接口尝试覆盖MongoDB中的文档,Postman测试无报错,但数据库内容未更新。相关代码及数据库文档格式如下:
原代码
const express = require("express"); const bodyParser = require("body-parser"); const ejs = require("ejs"); const mongoose = require("mongoose"); const app = express(); app.set('view engine', 'ejs'); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static("public")); mongoose.connect("mongodb://localhost:27017/wikiDB", {useNewUrlParser: true}); const articleSchema = { title: String, content: String }; const Article = mongoose.model("Article", articleSchema); // Requests Targeting All Routes app.route("/articles") .get(function(req, res) { Article.find() .then((foundArticles) => { mongoose.connection.close(); foundArticles.forEach(function(foundArticle) { // console.log(foundArticle); res.send(foundArticles); }) }) .catch(function(err) { console.log(err); }) }) .post(function(req, res) { const newArticle = new Article({ title: req.body.title, content: req.body.content }); newArticle.save() .then(function() { res.send("Successfully added a new article."); }) .catch(function(err) { console.log(err); }) }) .delete(function(req, res) { Article.deleteMany() .then(() => { res.send("Successfully deleted the document."); }) .catch(function(err) { console.log(err); }) }); // Requests Targeting Specific Routes app.route("/articles/:articleTitle") .get(function(req, res) { const title = req.params.articleTitle; Article.find({title}) .then((foundArticle) => { res.send(foundArticle); }) .catch(function(err) { console.log(err); }) }) // It won't allow the contents of the database to be overwritten. .put(function(req, res) { Article.replaceOne({ title: req.params.articleTitle }, { title: req.body.title, content: req.body.content, }) .then(() => { res.send("Successfully updated article."); }) .catch(function(err) { console.log(err); }) }) app.listen(3000, function() { console.log("Server started on port 3000!"); });
数据库文档格式
{ "_id" : ObjectId("6517a22854d8425f4e613d9e"), "title" : "REST", "content" : "REST is short for REpresentational State Transfer. It's an architectural style for designing APIs." }
问题排查与修复
1. 数据库连接被提前关闭
原GET请求中调用了mongoose.connection.close(),这会直接关闭数据库连接池,导致后续所有请求(包括PUT)无法操作数据库。Mongoose会自动维护连接池,无需手动关闭连接(除非应用程序终止)。
修复后的GET请求代码:
.get(function(req, res) { Article.find() .then((foundArticles) => { // 移除mongoose.connection.close(); res.send(foundArticles); // 直接返回查询结果,无需forEach遍历 }) .catch(function(err) { res.status(500).send(err); // 将错误返回给客户端,便于排查 }) })
2. PUT请求未验证更新结果
replaceOne方法在未找到匹配文档时不会抛出错误,仅会返回modifiedCount: 0,原代码直接返回成功信息,无法判断是否真的更新了数据。同时需确保查询条件与数据库文档完全匹配(MongoDB查询默认区分大小写)。
修复后的PUT请求代码:
.put(function(req, res) { Article.replaceOne( { title: req.params.articleTitle }, { title: req.body.title, content: req.body.content }, { runValidators: true } // 可选:确保更新内容符合Schema验证规则 ) .then((result) => { if (result.modifiedCount === 0) { return res.send("未找到匹配的文章,未执行更新操作"); } res.send("文章更新成功"); }) .catch(function(err) { res.status(500).send(err); }) })
3. Postman请求格式验证
发送PUT请求时,需选择x-www-form-urlencoded格式(与bodyParser.urlencoded对应),并正确填写title和content的键值对,否则req.body无法获取到更新数据。
可选优化:使用findOneAndReplace
若需要获取更新后的文档,可改用findOneAndReplace方法,它会返回修改后的文档(需设置new: true):
.put(function(req, res) { Article.findOneAndReplace( { title: req.params.articleTitle }, { title: req.body.title, content: req.body.content }, { new: true, runValidators: true } ) .then((updatedArticle) => { if (!updatedArticle) { return res.send("未找到匹配的文章"); } res.send(`文章更新成功:${JSON.stringify(updatedArticle)}`); }) .catch(function(err) { res.status(500).send(err); }) })
内容的提问来源于stack exchange,提问作者Stac Flo
相关产品推荐
相关产品推荐

