【问题标题】:MongoDB save() creating new document each time rather than updating existing documentMongoDB save() 每次创建新文档而不是更新现有文档
【发布时间】:2018-08-22 06:05:19
【问题描述】:

我正在使用这个函数保存到mongodb:

create(req, res, next) {
  let data = req.body;
  if(data) {
    let newIssue = this.lib.db.model('Issues')('data');
    console.log(newIssue);
    newIssue.save((err, emp) => {
      if(err) return next(this.RESTError('InternalServerError', err));
      this.writeHAL(res, emp);
    });
  } else {
    next(this.RESTError('InvalidArgumentError', 'No data received'));
  }
}

这是我的架构:

module.exports = {
  "id": "Issues",
  "properties": {
    "issue_title": {
      "type": "string",
      "description": "The title of the issue"
    },
    "issue_number": {
      "type": "string",
      "description": "The issue number"
    },
    "issue_url": {
      "type": "string",
      "description": "URL of the issue"
    }
  }
}

我对@9​​87654323@ 的理解是,如果文档已经存在于 mongodb 中,它会更新,但如果它不存在,则会创建一个新文档。但是,每次我发布同一个文档时,都会插入一个新文档,而不是更新现有文档。我怀疑这是因为在保存时,包含唯一 ID 的 _id 键被添加到我的架构中,从而使文档唯一。这是正确的吗?如果是,我该如何解决?

其他信息

我现在添加了一个 PUT。我的想法是我会用{upsert:true} 进行更新。我已经完成了部分工作,因为我可以 PUT 到 issue/{id} where{id}is the mongodb_id` 并更新现有文档。

这是我的 PUT:

update(req, res, next) {
  let data = req.body;
  let id = req.params.id;
  if(id) {
    this.lib.db.model('Issues')
      .findOne({_id: id})
      .exec((err, updateIssue) => {
        if(err) return next(this.RESTError('InternalServerError', err));
        updateIssue = Object.assign(updateIssue, data);
        updateIssue.update((err, issue) => {
          if(err) return next(this.RESTError('InternalServerError', err));
          this.writeHAL(res, issue);
        });
      });
  }
}

这是路由:

    controller.addAction({
      'path': '/issues/{id}',
      'method': 'PUT',
      'summary': "UPDATES the issues's information",
      'params': [swagger.pathParam('id', 'The id of the issue', 'string'),
    swagger.bodyParam('issue', 'the new information to update', 'string')],
      'responseClass': 'Issues',
      'nickname': 'updateIssue'
    }, controller.update);

我认为我不能将其用于 upsert,因为我没有 _id 开头,所以不能;无法创建路径。我的另一个选择是使用github_id。但是,每当我尝试将路由路径更改为/issues/{github_id} 或使用.findOne({github_id: id}) 之类的内容更新我的功能时,我都会收到错误消息。我需要能够使用/issues/{github_id} 并检查github_id 是否已经存在。如果是,则更新文档,如果不是,则创建一个新文档。

更多信息。

我已将更新功能更改为:

update(req, res, next) {
  let data = req.body;
  let id = req.params.id;
  if(id) {
    this.lib.db.model('Issues')
      .findOne({_id: id})
      .exec((err, updateIssue) => {
        if(err) return next(this.RESTError('InternalServerError', err));
        updateIssue = Object.assign(updateIssue, data);
        updateIssue.update({_id: id}, data, (err, issue) => {
          if(err) return next(this.RESTError('InternalServerError', err));
          this.writeHAL(res, issue);
        });
      });
  }
}

如果我在updateIssue.update({_id: id}, data, (err, issue) => { 行之后添加以下console.log

console.log('id: ', id);
console.log('data: ', data);
console.log('err: ', err);
console.log('issue: ', issue);

我得到这个输出:

id:  5b80307403eea4f14b06fe8c
data:  { _id: '5b80307403eea4f14b06fe8c',
  github_id: '347593262',
  issue_title: 'test issue XY',
  issue_number: '2',
  issue_url: 'https://api.github.com/repos/PCTestOrg/test1/issues/2a',
  __v: 0 }
err:  null
issue:  { n: 1, nModified: 0, ok: 1 }

我希望 issue_titletest issue X 更新到 test issue XY,但是更新不会发生。我在这里做错了什么?

【问题讨论】:

  • MongoDB 在内部使用“_id”来检查文档是否存在于数据库中。如果未提供“_id”,则从驱动程序创建一个新的 _id,并将插入到 DB 中。

标签: node.js mongodb mongoose put upsert


【解决方案1】:

如果您想创建或更新,请使用 upsert 更新

Model.update({_id: id}, obj, {upsert: true}, function (err) {...});

【讨论】:

  • 谢谢@Rahul Sharma。我正在努力思考如何才能做到这一点。我目前正在使用 newIssue.save。数据从 POST 路由到我的函数到 /issues。我将不得不使用 PUT 到 issues/{issue_id},这将使用启用 upsert 的更新路由到一个函数。这是正确的还是有更简单的方法?
【解决方案2】:

在阅读 this 帖子后,我无法进行 upsert 工作,因此最终得到以下结果:

update(req, res, next) {
  let data = req.body;
  let id = req.params.id;
  if(id) {
    this.lib.db.model('Issues')
      .findOne({_id: id})
      .exec((err, updateIssue) => {
        if(err) return next(this.RESTError('InternalServerError', err));
        updateIssue = Object.assign(updateIssue, data);
        updateIssue.save((err, issue) => {
          if(err) return next(this.RESTError('InternalServerError', err));
          this.writeHAL(res, issue);
        });
      });
  }
  else if(data) {
    let newIssue = this.lib.db.model('Issues')(data);
    console.log(newIssue);
    newIssue.save((err, issue) => {
      if(err) return next(this.RESTError('InternalServerError', err));
      this.writeHAL(res, issue);
    });
  } else {
    next(this.RESTError('InvalidArgumentError', 'No data received'));
  }
}

如果有人能告诉我,我相信有更好的方法可以做到这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多