我正在使用node.js实现一个函数,以更新mongoDB中的值。下面是我的mongoDB集合,
我想更新totalRating
数组内的totalVotes
和ratings
的值。因此,我在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
}
答案 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.totalRating
和ratings.totalVotes
试图在totalRating
下设置/创建字段totalVotes
和ratings
-如果它是一个对象,那么它将起作用。既然不是-那么您需要对数组中的哪个对象说应该执行此更新操作,如下所示:
{
$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)
}
)
});