findOneAndUpdate 函数用法详解 - Mongoose 教程

卡拉先生
发布于 2020年08月26日 | 上次编辑:2020年08月26日

mongoose
mongoose

前言

我们使用 mongoose 来操作 MongoDB 时,最基本的四个动作,「增、删、改、查」。其中「改」这个动作操作起来危险性和复杂性最高。一个小错误,可能会造成不可挽回的大问题。而「查」最关键的效率问题我们再下一篇教程中细讲,有关 Mongo 数据库高效搜索方案,推荐也可以试试「卡拉搜索」,一行代码即可快速部署,瞬间提升你的 Mongo 数据库搜索效率。

本教程要讲解 findOneAndUpdate() 在 Mongoose 中如何更新 MongoDB 中的数据。

我们用以下数据集作为本教程的演示案例

{ "_id" : ObjectId("5db6b24830f133b65dbbe457"), "name" : "Rocky", "age" : 3, "breed" : "Labrador" }
{ "_id" : ObjectId("5db6b25b30f133b65dbbe458"), "name" : "Max", "age" : 2, "breed" : "German Shephard" }
{ "_id" : ObjectId("5db6b26730f133b65dbbe459"), "name" : "Spike", "age" : 3, "breed" : "Great Dane" }
{ "_id" : ObjectId("5db6b27530f133b65dbbe45a"), "name" : "Tyke", "age" : 4, "breed" : "Pitbull" }
{ "_id" : ObjectId("5db6b28d30f133b65dbbe45b"), "name" : "Romeo", "age" : 2, "breed" : "Labrador" }

为了执行 HTTP endpoint testing,我们用 postman 来进行测试。大家可以从getpostman.com下载这个测试工具。

findOneAndUpdate()

findOneAndUpdate() 的功能就如同它的名字一样,在合集里查找对应的文档,然后按照我们的设定来进行更新。

当 Endpoint 执行“/update”时,将会调用以下 route handler 来处理

router.route("/update").post(function(req, res) {
  kennels.findOneAndUpdate({}, { age: 5 }, function(err, result) {
    if (err) {
      res.send(err);
    } else {
      res.send(result);
    }
  });
});

findOneAndUpdate() 包含有三个参数。

包含或不包含的查询对象,更新和回调函数。回调函数又有两个参数,错误(如果有错误的话)和结果。

上面这段代码,我们传递了一个空对象作为第一个参数,第二个对象是更新信息。我们把“age”字段“更改”为 5。

我们并不知道 findOneAndUpdate() 要记录哪个更新。

我们用 postman 工具来检查一下。

findOneAndUpdate 返回的结果
findOneAndUpdate 返回的结果

从结果可以看出,它返回了数据集的第一条文档。当没有指定查询时, findOneAndUpdate() 会更新数据集的第一个条文档。但为什么年龄没有更新呢?我们用 mongo shell 来检查一下。

mongo shell db.kennels.find() 检查代码
mongo shell db.kennels.find() 检查代码

我们可以看到,第一条文档的“age”已经更新为“5”,这正是我们刚刚那段代码执行完所期望的结果。这么说来,findOneAndUpdate() 的查询方法是在文档更新前,返回没有修改的匹配文档。

router.route("/update").post(function(req, res) {
  kennels.findOneAndUpdate({ breed: "Labrador" }, { name: "Mini" }, function(
    err,
    result
  ) {
    if (err) {
      res.send(err);
    } else {
      res.send(result);
    }
  });
});

上面这段代码是让 findOneAndUpdate() 来查询“Labrador” 并将“name”字段更改为“Mini”。

但是当我们检查数据集时,会发现其实有两个文档的值都是“Labrador”。那么上面这段代码会怎么执行呢?

让我们通过工具检查一下,看看会返回什么结果。

findOneAndUpdate 返回的结果
findOneAndUpdate 返回的结果

正如前文所说,findOneAndUpdate() 在更新之前,会先返回匹配的文档。所以我们可以看到,findOneAndUpdate() 匹配到了第一个文档,其中的“breed”值是“Labrador”。

这就是 findOneAndUpdate() 的工作原理。不论数据集中有多少可以匹配的查询文档,findOneAndUpdate() 只会更新第一个匹配上的文档,然后忽略其他所有文档。

我们来用 mongo shell 来检查一下。

mongo shell db.kennels.find() 检查代码
mongo shell db.kennels.find() 检查代码

如图所示,和我们的预期一致。第一个文档中“breed”中的值已经更改为“Labrador”。

总结

findOneAndUpdate() 的使用方法是不是很奇妙,希望本教程能对你有所帮助。

更多数据库教程欢迎查看扩展阅读,也欢迎给我们留言,交流你的想法。

扩展阅读

数据库 系列教程

相关文章

友情链接更新日志© 2020, 卡拉搜索, Built with ❤️ in San Francisco + Beijing

京ICP备15049164号-3