【问题标题】:Update route and model for MongoDB either removes data or throws an error更新 MongoDB 的路由和模型会删除数据或引发错误
【发布时间】:2019-08-06 01:50:30
【问题描述】:

我已经搜索了一段时间,但没有遇到与我遇到的问题非常相似的问题。

我正在开发一个具有四个路由的 MERN 堆栈应用程序。其中三条路线运行良好,但我的第四条路线和数据库模型给我带来了麻烦。

这是模型:

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

let bucketListItem = new Schema({
itemOnList: { type: String, required: true },
status: { type: String, required: true },
dateCreated: { type: Date, default: Date.now },
completed: { type: Boolean, default: false }
});

module.exports = mongoose.model("bucketListItem", 
bucketListItem);

这是我在 Postman 中用于测试更新功能的 JSON(我从 GET 请求中复制了它,这就是它具有 _id 和 __v 的原因):

{
"completed": true,
"_id": "5c8b05c701eb8007dceb3aaa",
"itemOnList": "Visit Venice",
"status": "btdt.",
"dateCreated": null,
"__v": 0
}

正如您在模型中看到的,我有四个字段,其中两个我已设置为“必需:true”。当我尝试更新任何字段时,例如将 true 切换为 false 或将状态更改为不同的消息,我收到一条错误消息,指出这两个字段都是必需的,即使所有字段都包含信息。

这是错误信息:

{
"error": {
    "errors": {
        "status": {
            "message": "Path `status` is required.",
            "name": "ValidatorError",
            "properties": {
                "message": "Path `status` is required.",
                "type": "required",
                "path": "status"
            },
            "kind": "required",
            "path": "status"
        },
        "itemOnList": {
            "message": "Path `itemOnList` is required.",
            "name": "ValidatorError",
            "properties": {
                "message": "Path `itemOnList` is required.",
                "type": "required",
                "path": "itemOnList"
            },
            "kind": "required",
            "path": "itemOnList"
        }
    },
    "_message": "bucketListItem validation failed",
    "message": "bucketListItem validation failed: status: Path `status` is required., itemOnList: Path `itemOnList` is required.",
    "name": "ValidationError"
  }
}

现在,我尝试从模型中删除“required: true”,并且不再收到错误消息。

相反,路由完全从数据库条目中删除信息,我收到如下信息:

{       
 "completed": false,
 "_id": "5c8b05c701eb8007dceb3aaa",
 "__v": 0,
 "dateCreated": "null"
}

这是我的路线的代码:

blRoutes.route("/update/:id").post(function(req, res) {
BucketListItem.findById(req.params.id, function(err, 
bucketListItem) {
if (!bucketListItem) {
  res.status(404).send("Data not found.");
} else {
  bucketListItem.itemOnList = req.body.itemOnList;
  bucketListItem.status = req.body.status;
  bucketListItem.dateCreated = req.body.dateCreated;
  bucketListItem.completed = req.body.completed;

  bucketListItem
    .save()
    .then(bucketListItem => {
      res.json("Updated.");
    })
    .catch(err => {
      res.status(400).send({ error: err });
      console.log(err);
    });
  }
});
});

app.use("/bucketList", blRoutes);

我一直在使用 Body Parser 和 CORS,以防万一读到这篇文章的人对此感到疑惑:

app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

我希望我没有以不清楚的方式表达这一点或遗漏任何内容。如果我有,请告诉我。

提前感谢您的帮助!

更新:

所以我重构了,(我希望这是正确的词),我的路线,现在看起来像这样:

blRoutes.route("/update/:id").post(function(req, res) {
BucketListItem.findOneAndUpdate({ _id: req.params.id }, req.body, {upsert: true, returnNewDocument: true})
.then(bucketListItem => res.json(bucketListItem))
.catch(err => res.status(404).send(err));
});

(上面写着 {upsert: true},我也试过 {new: true}。

我对模型进行了一些重构:

let bucketListItem = new Schema({
itemOnList: { type: String, required: true },
status: { type: String, required: true },
dateCreated: { type: Date, default: Date.now() },
completed: Boolean
});

我的所有其余代码都保持不变。

当我运行这段代码时会发生什么,我试图更改的文档,

{
"dateCreated": null,
"_id": "5c8b05c701eb8007dceb3aaa",
"completed": false,
"itemOnList": "Visit Venice",
"status": "Bought tickets.",
"__v": 0
}

返回完全相同。什么都不会改变。我正在尝试将其更改为:

    {
    "completed": true,
    "_id": "5c8b05c701eb8007dceb3aaa",
    "itemOnList": "Visit Venice",
    "status": "btdt.",
    "dateCreated": null,
    "__v": 0
    }

据我所知,我的路线代码是正确的,但我确信有一些我没有注意到的小东西。 再次感谢您的帮助。

【问题讨论】:

  • 这些是来自 mongoose 的验证错误,很可能是因为 POST 的 req.body 中的值无效,甚至没有提供。您的第一步是检查 req.body 并确保它实际上包含您所期望的,因为它可能不包含。

标签: javascript mongodb express mongoose


【解决方案1】:

您可以使用此查询简单地更新文档:-

BucketListItem.findOneAndUpdate(
 { _id: req.params.id },
 req.body,
 { new: true, upsert: true }
);

此外,您不必将字段的默认设置为 false。只需将类型提及为布尔值,而不是传递具有类型的对象。

let bucketListItem = new Schema({
itemOnList: { type: String, required: true },
status: { type: String, required: true },
dateCreated: { type: Date, default: Date.now },
completed: Boolean
});

【讨论】:

  • 感谢您的帮助。我尝试了您建议的更改,并且我之前提到的错误消失了,但现在我得到并清空对象作为响应。我尝试添加 {new: true} 和 {upsert: true},但它们似乎没有做任何事情。还有什么我可能会遗漏的吗?
  • 能否请您更新您现在使用的代码,以便我查看。
  • blRoutes.route("/update/:id").post(function(req, res) { BucketListItem.findOneAndUpdate({ _id: req.params.id }, req.body) .then(bucketListItem => req.json(bucketListItem)) .catch(err => res.status(404).send(err)); });
  • 这里有一个错字。它应该是 res.json(bucketListItem) 而不是 req.json。你的代码中也是这样吗?我在这里没有看到任何其他问题。您说您已经尝试过传递 upsert 和新选项,对吗?请也更新该代码。
  • 您的架构有错字。您正在调用 Date.now() 而不是它应该只是 Date.now。 returnNewDocument 也不是一个有效的选项。只需通过 new: true ,您应该一切顺利。检查更新的答案。如果您正在检查的 id 不存在任何文档,则 upsert true 选项将创建一个新文档。因此,如果这是您想要的,则仅包含 upsert true 否则只需将 new 传递给 true。
猜你喜欢
  • 1970-01-01
  • 2021-07-22
  • 2014-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-11
  • 1970-01-01
  • 2011-06-17
相关资源
最近更新 更多