Mongoose `findOneAndUpdate` 回调不传递更新的文档
Posted
技术标签:
【中文标题】Mongoose `findOneAndUpdate` 回调不传递更新的文档【英文标题】:Mongoose `findOneAndUpdate` callback does not pass an updated document 【发布时间】:2020-08-10 07:11:46 【问题描述】:我在model.js
文件中分离了我的Mongoose 代码,而用于处理http 请求的Express 代码在app.js
中。我只是在为一个虚构的 wiki 文章站点练习创建 API 并在 Postman 上对其进行测试。问题在于findOneAndUpdate
api。它正在按预期更改数据库文档,但是,传递给findOneAndUpdate
api 回调的假定更新文档只是原始文档(修改前),而不是新更新的文档。我控制台记录了它只是为了确认。理想的做法是在回调中传递新更新的文档,以便万一我需要将新更新的文档作为 JSON 中的响应发送,只是为了显示更改确认。
我在下面分享了我的代码。
(注意:为简洁起见,我只包含了相关代码,即来自app.js
的app.put('/articles/:articleTitle' ....
,以及它从model.js
- updateReplaceArticleInDB
调用的静态方法。
app.js
const express = require('express');
const bodyParser = require('body-parser');
const model = require('./model');
const app = express();
app.use(bodyParser.urlencoded( extended: true ));
app.put('/articles/:articleTitle', async (req, res) =>
const articleTitle = req.params.articleTitle;
const newArticleTitle = req.body.title;
const newArticleContent = req.body.content;
try
const response = await model.DBUtility.updateReplaceArticleInDB(articleTitle, newArticleTitle, newArticleContent);
res.json(message: 'Successfully overwritten article', updatedArticle: response, app: 'wiki-api');
catch (err)
res.json(message: err, app: 'wiki-api');
);
const port = 3000;
app.listen(port, () =>
console.log(`Server started on port $port`);
);
model.js
const mongoose = require('mongoose');
//connect to DB
mongoose.connect('mongodb://localhost:27017/wikiDB', useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false ,
(err) =>
try
console.log(`Server connected successfully to MongoDB`);
catch (err)
console.log(err);
);
const articleSchema = new mongoose.Schema(
title: String,
content: String
);
const Article = mongoose.model('Article', articleSchema);
class DBUtility
static updateReplaceArticleInDB(articleTitle, newArticleTitle, newArticleContent)
return new Promise((resolve, reject) =>
Article.findOneAndUpdate(
title: articleTitle,
$set: title: newArticleTitle, content: newArticleContent, (err, updatedArticle) =>
if (err)
reject(err);
else
console.log(`updatedArticle: $updatedArticle`);
resolve(updatedArticle);
);
);
exports.DBUtility = DBUtility;
我的数据库中有 5 篇文章(5 个文档):
"_id" : "5c139771d79ac8eac11e754a",
"title" : "API",
"content" : "API stands for Application Programming Interface. It is a set of subroutine definitions, communication protocols, and tools for building software. In general terms, it is a set of clearly defined methods of communication among various components. A good API makes it easier to develop a computer program by providing all the building blocks, which are then put together by the programmer."
/* 2 */
"_id" : "5c1398aad79ac8eac11e7561",
"title" : "Bootstrap",
"content" : "This is a framework developed by Twitter that contains pre-made front-end templates for web design"
/* 3 */
"_id" : "5c1398ecd79ac8eac11e7567",
"title" : "DOM",
"content" : "The Document Object Model is like an API for interacting with our html"
/* 4 */
"_id" : "5ea2c188fa57aa1b6453eda5",
"title" : "Node JS",
"content" : "Node.js is an open-source, cross-platform, javascript runtime environment that executes JavaScript code outside of a web browser. Node.js lets developers use JavaScript to write command line tools and for server-side scripting—running scripts server-side to produce dynamic web page content before the page is sent to the user's web browser. Consequently, Node.js represents a \"JavaScript everywhere\" paradigm,[6] unifying web-application development around a single programming language, rather than different languages for server- and client-side scripts.",
"__v" : 0
/* 5 */
"_id" : "5ea2d5304e19b11e0013a86a",
"title" : "Bootstrap",
"content" : "Bootstrap is an open source
toolkit for developing with HTML, CSS, and JS. Quickly prototype your ideas or build your entire app with our Sass variables and mixins, rins, responsive grid system, extensive prebuilt components, and powerful plugins
built on jQuery.",
"__v" : 0
目标是将最后一个文档"title" : "Bootstrap"
更改为"title" : "EJS"
和"content" : "EJS is a simple templating language ..."
。
但是,当我在 Postman 上发出 http 请求时,返回的文档(应该是新更新的文档)不是。它显示为原来的旧版本(即"title": "Bootstrap"
而不是"title": "EJS"
):
在终端中,控制台记录的updatedArtilce
对象传递给updateReplaceArticleInDB
api的回调也显示旧文章title: Bootstrap
,而不是更新后的EJS
:
[nodemon] starting `node app.js`
Server started on port 3000
Server connected successfully to MongoDB
updatedArticle:
_id: 5ea2d5304e19b11e0013a86a,
title: 'Bootstrap',
content: 'Bootstrap is an open source
toolkit for developing with HTML, CSS, and JS. Quickly prototype your ideas or build your entire app with our Sass variables and mixins, rins, responsive grid system, extensive prebuilt components, and powerful plugins
built on jQuery.'
但数据库确实成功更改了文档。只是 Mongoose API 在其回调中传递旧文档而不是新更新的文档。
【问题讨论】:
添加new: true
作为 findOneAndUpdate 查询的一部分
太棒了。谢谢。
【参考方案1】:
正如您在documentation 中看到的,为了通过findOneAndUpdate
函数调用获取更新的文档,您需要将returnOriginal: false
或new: true
作为选项字段的参数传递。这是一个例子:
const filter = name: 'Jean-Luc Picard' ;
const update = age: 59 ;
// `doc` is the document after `update` was applied because of `returnOriginal: true`
const doc = await Character.findOneAndUpdate(filter, update,
returnOriginal: false
);
doc.name; // 'Jean-Luc Picard'
doc.age; // 59
【讨论】:
太棒了。谢谢你。我确实多次阅读了文档的这一部分,但是由于代码的格式,它将结果分配给一个常量,我希望有一个回调函数而不是适合我的代码,我在其他地方寻找示例并忘记了new:true
选项 arg。再次感谢。
乐于助人。
我不知道为什么,但 new: true
曾经工作过。但是,它不再。好消息是returnOriginal: false
有效!非常感谢你的队友以上是关于Mongoose `findOneAndUpdate` 回调不传递更新的文档的主要内容,如果未能解决你的问题,请参考以下文章
mongoose入门以及 mongoose 实现数据 的增删改查
Mongoose 错误 - 具有相同型号名称的 Mongoose 型号
使用 mongoose.createConnection() 与 mongoose.connect() 时查询挂起