findOneAndUpdate()不更新值

时间:2020-05-16 14:47:12

标签: node.js mongodb mongoose

我正在使用node.js实现一个函数,以更新mongoDB中的值。下面是我的mongoDB集合,

enter image description here

我想更新totalRating数组内的totalVotesratings的值。因此,我在node.js中实现了以下功能。

router.post('/addReview', (req, res) => {

   Product.findOneAndUpdate(
       {_id: req.body.productId},
       {
           "$set" : {
                    "ratings.totalRating": req.body.rating,
                    "ratings.totalVotes" : req.body.votes
           }
       },
       {new : true},
       (err, productInfo) => {
           if(err) return res.json({success:false, err});
           res.status(200).json(productInfo)
       }
   )
});

下面是Product模式,

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const AddItemsSchema = new Schema({
    _id: {type:String, required:true},
    img: {type:String, required: true},
    category: {type:String, required: true},
    name: {type:String, required: true},
    description: {type:String, required: true},
    price: {type:String, required: true},
    quantity: {type:String, required: true},
    size: {type:String, required: true},
    meterial: {type:String, required: true},
    discount:{type:Number, default: 0},
    comment:{type:Array, default: []},
    ratings:{type:Array, required: true}
});

const Products = mongoose.model('additems', AddItemsSchema);

module.exports = Products;

当我使用邮递员发送邮寄请求时,它不更新db值,并且返回null。有人可以指出我做错了什么吗?谢谢!

邮递员请求正文,

{
    "productId": "5eb82cd3e8b80155fc3ee021",
    "rating" : 4.0,
    "votes" : 1
}

2 个答案:

答案 0 :(得分:1)

您的代码中有几个问题:

1)第一个主要问题不是查询的更新部分,而是过滤器部分:

.findOneAndUpdate(filterPart, updatePart)

因此,从.findOneAndUpdate()的基本功能开始- 如果找不到带有输入过滤器的文档,则返回null。如果它找到一个文档并且由于某种原因无法更新它,它将返回一个错误或旧文档(如果查询语法没有问题并且没有执行更新)。

也请注意::使用选项{ upsert : true }时 如果没有{ new : true },并且没有匹配的文档,则 尽管它创建了一个新文档,结果仍然是null。它的 因为最初findOneAndUpdate找不到任何文档。

因此,您遇到的问题是输入req.body.productId的类型为string,但是您数据库中的_id的类型为ObjectId(),需要在查询数据库之前进行转换像这样:

const mongoose = require("mongoose");

router.post("/addReview", (req, res) => {
  Product.findOneAndUpdate(
    { _id: mongoose.Types.ObjectId(req.body.productId) },
    {
      $set: {
        "ratings.0.totalRating": req.body.rating,
        "ratings.0.totalVotes": req.body.votes,
      },
    },
    { new: true },
    (err, productInfo) => {
      if (err) return res.json({ success: false, err });
      res.status(200).json(productInfo);
    }
  );
});

2)更新部分也存在问题:

由于ratings是对象[{},{}]的数组,因此您不能像下面这样:

{
    "$set" : {
              "ratings.totalRating": req.body.rating,
              "ratings.totalVotes" : req.body.votes
      }
}

由于$set运算符ratings.totalRatingratings.totalVotes试图在totalRating下设置/创建字段totalVotesratings-如果它是一个对象,那么它将起作用。既然不是-那么您需要对数组中的哪个对象说应该执行此更新操作,如下所示:

{
  $set: {
    "ratings.0.totalRating": req.body.rating,
    "ratings.0.totalVotes": req.body.votes,
  },
}

我们将从上方更新ratings数组中的第一个对象。通常,如果始终只有个对象,则将ratings设置为对象而不是数组,否则将其设置为多个对象< / strong>,然后将其保留为数组,并为每个对象添加一个唯一值。在更新中使用positional运算符时,这有助于确定需要更新哪个特定对象。

答案 1 :(得分:0)

您需要提供索引以更新数组

   router.post('/addReview', (req, res) => {

   Product.findOneAndUpdate(
       {_id: req.body.productId},
       {
           "$set" : {
                    "ratings.0.totalRating": req.body.rating,
                    "ratings.0.totalVotes" : req.body.votes
           }
       },
       {new : true},
       (err, productInfo) => {
           if(err) return res.json({success:false, err});
           res.status(200).json(productInfo)
       }
   )
});