MongoDB save()每次都创建新文档,而不是更新现有文档

时间:2018-08-22 06:05:19

标签: node.js mongodb mongoose put upsert

我正在使用此功能保存到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"
    }
  }
}

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

其他信息

我现在添加了一个PUT。我的想法是我将使用{upsert:true}进行更新。我之所以这样做,是因为我可以将其放置到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);
        });
      });
  }
}

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

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,但是不会发生更新。我在这里做什么错了?

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

我无法进行高难度的工作,因此在阅读this帖子后最终获得了以下内容:

    [DllImport("user32.dll")]
    static extern IntPtr LoadImage(
        IntPtr hinst,
        string lpszName,
        uint uType,
        int cxDesired,
        int cyDesired,
        uint fuLoad);

    public MainWindow()
    {
        InitializeComponent();

        var image = LoadImage(IntPtr.Zero, "#106", 1, SystemInformation.SmallIconSize.Width, SystemInformation.SmallIconSize.Height, 0);
        var imageSource = Imaging.CreateBitmapSourceFromHIcon(image, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());

        // Set button content from code
        var sp = new StackPanel
        {
            Orientation = Orientation.Horizontal,
        };
        sp.Children.Add(new Image { Source = imageSource, Stretch = Stretch.None });
       sp.Children.Add(new TextBlock { Text = "OK", Margin = new Thickness(5, 0, 0, 0) });
        OkButton.Content = sp;
    }

我敢肯定,如果有人可以告诉我我会很感激的话,还有更好的方法。