【问题标题】:MongoDB/Mongoose: Updating entire document with findOneAndUpdate()MongoDB/Mongoose:使用 findOneAndUpdate() 更新整个文档
【发布时间】:2016-10-15 21:07:35
【问题描述】:

我想使用findOneAndUpdate() 方法来创建一个不存在的文档,或者如果存在则更新它。考虑以下代码:

SampleComment = new Comment({
    id: '00000001',
    name: 'My Sample Comment',
    ...
})

这是我试图找出 SampleComment 是否已经存在,如果存在,更新它,否则创建它:

Comment.findOneAndUpdate(
    { id: SampleComment.id }, 
    { SampleComment }, // <- NOT PASSING THE OBJECT
    { upsert: true, setDefaultsOnInsert: true }, 
    function(error, result) {
        ...
});

我试图将模型实例作为第二个参数中的对象传递,但结果仅返回模型的默认值。文档本身也是如此。

如何在第二个参数中正确传递整个对象SampleComment?

【问题讨论】:

    标签: javascript mongodb mongoose


    【解决方案1】:

    当您使用Document 对象作为更新对象调用findOneAndUpdate() 并使用{ SampleComment } 时实际发生的情况是您将其解构为SampleComment : {...}。

    Mongoose 然后会查看您的数据库文档中是否有任何名为SampleComment 的属性,但没有找到,然后什么也不做。返还给您的文件不会有任何改变。

    您可以做些什么来解决这个问题,首先使用 Mongoose 的 toObject() 方法将您的 Document 转换回普通更新对象,删除 _id (因为该属性是不可变的,并且您不想将其替换为更新),然后使用您现有的 findOneAndUpdate() 方法保存它。例如:

    let newComment = SampleComment.toObject();
    delete newComment._id;
    
    Comment.findOneAndUpdate(
        { id: SampleComment.id }, 
        newComment,
        { upsert: true, setDefaultsOnInsert: true }, 
        function(error, result) {
            ...
        }
    );
    
    

    然后您可以在数据库中看到更新后的文档。要在您的 result 中接收更新的文档,您还需要将选项 { new: true } 传递给您的选项对象。

    这里是 Mongoose 的 toObject() Document 方法文档的链接。

    【讨论】:

      【解决方案2】:

      默认情况下,返回的结果将是未更改的文档。如果您希望返回新的、更新的文档,您必须传递一个名为 new 的附加参数,其值为 true。

      Comment.findOneAndUpdate({id: SampleComment.id}, SampleComment, {new: true, upsert: true, setDefaultsOnInsert: true}, function(error, result) {
          if(error){
              console.log("Something wrong when updating data!");
          }
      
          console.log(result);
      });
      

      见http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate:

      function(error, doc) {
        // error: any errors that occurred
        // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
      }
      

      【讨论】:

      • 我尝试了{new: true} 参数,但似乎还有其他问题。当添加$set 我得到:[TypeError: Cannot read property 'toObject' of null]
      • 尝试在控制台打印出SampleComment,看看它是否不为空。另外,我从帖子中删除了 $set,尝试将 SampleComment 放在不带花括号的位置。
      • console.log 返回包含所有属性的完整对象。我试过删除 $set 和大括号。错误消失了,但是对象仍然没有被传递,并且 db 文档仍然是空的,但是默认值。
      • 我正在寻找相同的。我从一个表单(带有 22 个字段)发送对象,因此编写所有字段根本不切实际。最好的方法是覆盖文档或类似内容。你找到@ComfortEagle 的出路了吗?
      • 这实际上并不能解决问题。将 Document 作为更新对象传递时,数据库不会更新,也不会引发错误。可以确认。 @ComfortEagle 你解决过这个问题吗?
      【解决方案3】:

      我找到了让它变得简单快捷的方法:D

      在我的情况下,我只需要从表单中插入对象并更新文档。也许这对某人有帮助:

      Angularjs 控制器:

        $scope.bike ={};
        fBikeFactory.get({
              id:$stateParams.id
            })
            .$promise.then(function (response) {
              $scope.bike = response;
            },function (response) {
              $scope.bike = "Error: " + response.status + " " + response.statusText;
            });
      
      
      // UPDATE a BIKE
            $scope.saveBike = function() {
              $scope.processing = true;
      
              var updateQuery = fBikeFactory.update({id: $stateParams.id}, $scope.bike);
              updateQuery.$promise.then(function(rep) {
                  $scope.processing = false;
                  $scope.message = "Desat amb èxit";
                  setTimeout(function(){ $state.go('home.adminBikes');$scope.bike.message = ''; }, 750);
              },function(err) {
                  $scope.processing = false;
                  $scope.message = 'Error al Desar, torna a provar-ho.';
              })
            };
      

      需要型号:

      var Bike = require('../models/bikeModel.js');
      

      ...

      路线:

      bikesRouter.route('/bikes/:id')
          .put(function(req,res) {
      
      
          Bike.findOneAndUpdate(
                  {_id: req.params.id}, // find a document with that filter
                  req.body, // document to insert 
                  {upsert: true, new: true, runValidators: true}, // options
                  function (err, updatedBike) { // callback
                      if (err) console.log('ERROR '+ err);
                      else res.json(updatedBike)
      
                  }
              );
          });
      

      希望对你有所帮助:D

      【讨论】:

        猜你喜欢
        • 2017-08-13
        • 1970-01-01
        • 2021-03-26
        • 2019-10-05
        • 2020-11-19
        • 2022-08-02
        • 2016-04-30
        • 2017-01-06
        • 1970-01-01
        相关资源
        最近更新 更多