将对象推入数组(如果尚不存在),否则更新

时间:2019-10-08 17:18:31

标签: javascript mongodb mongoose

在基于express的node.js服务器中,通过mongoose与mongo db进行交互,我只想在用户(由其ID标识)未检查以下内容的情况下,在“ reviews”数组中插入“ review”产品,否则,请更新先前插入的评论。 鉴于以下mongo方案:

产品:

var ProductSchema = new Schema({
  ownerId: {
    type: Schema.ObjectId,
    required: 'Owner of recharge point required'
  },
  name: {
    type: String,
    required: 'The name is required'
  },      
  description: {
    type: String
  },
  reviews: {
    type: [Review]
  }
});

评论:

  var ReviewSchema = new Schema({
  reviewerId: {
    type: ObjectId,
    required: 'Reviewer id required',
    ref: 'User' <not showed>
  },
  review: {
    type: String
  },
  date: {
    type: Date, 
    default: Date.now
  }
});

这是我想出的结果,但这仅插入新评论,尚未更新它们。 我认为我的解决方案可以进行很多改进(和简化)。

exports.review_product = function (req, res) {
    const review = req.body.review;
    const reviewerId = req.body.reviewerId;
    const productId = req.params.productId;

    Product.findOne({_id: productId}, function(error, result){
          if(error) {
               res.status(500).send({message: error}).end()
           } else if(result){
               var newReview = new Review({ reviewerId: reviewerId, review: review});
               Product.findOneAndUpdate({ _id: productId, 'reviews.reviewerId': { $ne: reviewerId }}, 
                 { $push: { 'reviews': newReview}},
                 function(error, found) {
                     if (error) {
                        res.status(500).send({message: error}).end()
                     } else if(found) {
                        res.status(200).send({message: 'Review succefully added.'}).end()
                     } else {
                        res.status(404).send({message: 'You already reviewed this product'}).end()
                     }
              });
           } else {
               res.status(404).send({message: 'Cannot find the product to be reviewed.'}).end()
           }
  })
};

2 个答案:

答案 0 :(得分:0)

您可以使用函数include()

例如:

var array = ["a","b","c"];
console.log(array.includes("a"); //return true
console.log(array.includes("z"); //return false because is not exist

只需将变量字符串替换为对象,即可使其适应您的代码

答案 1 :(得分:0)

最好的方法是用猫鼬进行查询,以先检查产品的审阅者ID。您还可以使用async / await使代码更具可读性。

可能看起来像(请注意,这是伪代码):

exports.reviewProduct = async (req, res) => {
    const review = req.body.review;
    const reviewerId = req.body.reviewerId;
    const productId = req.params.productId;

    const hasReviewed = await Product.find({_id: productId, 'reviews.reviewerId': { $eq: reviewerId } )

    if(hasReviewed) {
        Product.findOneAndUpdate({
            _id: productId, 
            reviews: { $elemMatch: { reviewerId: reviewerId } }
            },
            { $set: {
                'review.$.title': review.title,
                'review.$.body': review.body
             }},
             {'new': true, 'safe': true, 'upsert': true})
    } else {
        Product.findOneAndUpdate(
            { _id: productId }, 
            { $push: { reviews: review } },
            {safe: true, upsert: true, new : true},
            (err, model) => {
               console.log(err);
            })
    }
}