使用Mongoose调用updateOne/updateMany更新MongoDB文档报错
解决Mongoose更新MongoDB文档的PUT请求错误
问题描述
使用Mongoose更新MongoDB文档时,调用updateOne()和updateMany()方法均触发相同错误,仅PUT请求异常,GET、POST、DELETE请求均正常工作。
代码示例
const uri = "mongodb+srv://username:password@generalpurpose.bxoapvc.mongodb.net/wikiDB?retryWrites=true&w=majority"; mongoose.connect(uri, { useNewUrlParser: true }); const articleSchema = new mongoose.Schema({ title: String, content: String, }); const Article = mongoose.model("Article", articleSchema); app.put("/articles/:articleTitle", (req, res) => { Article.updateOne( { title: req.params.articleTitle }, { title: req.body.title, content: req.body.content }, { overwrite: true } ).then((updated, e) => { if (updated) { res.send("Article successfully"); } else { res.send(e); } }); });
报错信息
调用updateOne()时的错误
/home/ahmedhassan/wiki-api/node_modules/mongoose/lib/query.js:3787 throw new MongooseError('The MongoDB server disallows ' + ^ MongooseError: The MongoDB server disallows overwriting documents using `updateOne`. See: https://mongoosejs.com/docs/deprecations.html#update at model.Query._updateThunk (/home/ahmedhassan/wiki-api/node_modules/mongoose/lib/query.js:3787:13) at model.Query._updateOne (/home/ahmedhassan/wiki-api/node_modules/mongoose/lib/query.js:3881:23) at model.Query.exec (/home/ahmedhassan/wiki-api/node_modules/mongoose/lib/query.js:4330:28) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) Node.js v18.16.0 [nodemon] app crashed - waiting for file changes before starting...
调用updateMany()时的错误(错误#01)
/home/ahmedhassan/wiki-api/node_modules/mongoose/lib/query.js:3787 throw new MongooseError('The MongoDB server disallows ' + ^ MongooseError: The MongoDB server disallows overwriting documents using `updateMany`. See: https://mongoosejs.com/docs/deprecations.html#update at model.Query._updateThunk (/home/ahmedhassan/wiki-api/node_modules/mongoose/lib/query.js:3787:13) at model.Query._updateMany (/home/ahmedhassan/wiki-api/node_modules/mongoose/lib/query.js:3868:23) at model.Query.exec (/home/ahmedhassan/wiki-api/node_modules/mongoose/lib/query.js:4330:28) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) Node.js v18.16.0 [nodemon] app crashed - waiting for file changes before starting...
调用update()时的错误(错误#02)
TypeError: Article.update is not a function at /home/ahmedhassan/wiki-api/app.js:85:13 at Layer.handle [as handle_request] (/home/ahmedhassan/wiki-api/node_modules/express/lib/router/layer.js:95:5) at next (/home/ahmedhassan/wiki-api/node_modules/express/lib/router/route.js:144:13) at next (/home/ahmedhassan/wiki-api/node_modules/express/lib/router/route.js:140:7) at next (/home/ahmedhassan/wiki-api/node_modules/express/lib/router/route.js:140:7) at Route.dispatch (/home/ahmedhassan/wiki-api/node_modules/express/lib/router/route.js:114:3) at Layer.handle [as handle_request] (/home/ahmedhassan/wiki-api/node_modules/express/lib/router/layer.js:95:5) at /home/ahmedhassan/wiki-api/node_modules/express/lib/router/index.js:284:15 at param (/home/ahmedhassan/wiki-api/node_modules/express/lib/router/index.js:365:14) at param (/home/ahmedhassan/wiki-api/node_modules/express/lib/router/index.js:376:14)
解决方案
错误原因
Mongoose新版本中,updateOne/updateMany方法被限制直接覆盖整个文档;同时update()方法已被废弃,不再支持调用。
方案1:使用replaceOne()方法
replaceOne()是Mongoose提供的专门用于替换整个文档的方法,无需额外设置overwrite: true参数:
app.put("/articles/:articleTitle", (req, res) => { Article.replaceOne( { title: req.params.articleTitle }, { title: req.body.title, content: req.body.content } ).then((result) => { if (result.modifiedCount > 0) { res.send("文章更新成功"); } else { res.send("未找到匹配的文章或无需更新"); } }).catch((err) => { res.send(err); }); });
方案2:使用findOneAndUpdate()方法
若需要返回更新后的文档,或实现更灵活的更新逻辑,可使用findOneAndUpdate()并添加overwrite: true参数:
app.put("/articles/:articleTitle", (req, res) => { Article.findOneAndUpdate( { title: req.params.articleTitle }, { title: req.body.title, content: req.body.content }, { overwrite: true, new: true } // new: true 配置返回更新后的文档 ).then((updatedArticle) => { if (updatedArticle) { res.send("文章更新成功"); } else { res.send("未找到匹配的文章"); } }).catch((err) => { res.send(err); }); });
额外注意点
原代码中then((updated, e) => {})的参数处理不规范,Mongoose的Promise应通过catch()捕获异常,而非在then()中接收错误参数,上述方案已修正该问题。
内容的提问来源于stack exchange,提问作者Ahmed Hassan
相关产品推荐
相关产品推荐

