在 updateOne mongoose 方法中更新现有或使用 mongo 运算符的功能

Posted

技术标签:

【中文标题】在 updateOne mongoose 方法中更新现有或使用 mongo 运算符的功能【英文标题】:Update in function of existing or using mongo operator in updateOne mongoose method 【发布时间】:2021-07-19 20:04:12 【问题描述】:

情况:

我有一个赞按钮,我希望当用户点击数据库中的赞时:

如果用户还不喜欢它,则增加(如 +1 并从 likeBy 数组添加用户 ID)

如果用户已经喜欢它,则减少(如 - 1 并从 likeBy 数组中删除使用的 id)

代码:

控制器:

exports.likeIdea = (req,res,next) => 
    const userId = getUserId(req)
    Ideas.updateOne( _id: req.params.id, 
      $set: 
        like:  
            $cond: [ $in: [userId, "$likedBy"],  $inc:  like: +1   ,  $inc:  like: -1   ] 
        ,
        likedBy:  
            $cond: [ $in: [userId, "$likedBy"],  $pull:  likedBy: userId   ,  $push:  likedBy: userId   ] 
        ,
        _id: req.params.id
      
    )
    .then(() => res.status(200).json( message: 'Success'))
    .catch(error => 
      res.status(400).json( error )
    );
;

架构

const ideaSchema = mongoose.Schema(  
    name:  type: String, required: true,  
    sumup:  type: String, required: true ,  
    description:  type: String, required: true,  
    published: type: Boolean, required: true,  
    like: type: Number, required: true,  
    likedBy: type: [String],  
    author: type: String, required: true,  
    dislike: type: Number, required: true,  
    dislikedBy: type: [String],     
    imgUrl: type: String, required: true 
);  

错误:

CastError: Cast to Number failed for value " '$cond': [ '$in': [Array] , '$inc': [Object] , '$inc': [Object] ] " 在路径 "like" [...] messageFormat: undefined, stringValue: '" '$cond': [ '$in': [数组] , '$inc': [Object] , '$inc': [对象] ] "', kind: 'Number', value: ..., path: 'like', ...

【问题讨论】:

你不需要额外的+ - $inc: like: +1 你可以使用 $inc: like: 1 【参考方案1】:

常规更新查询不允许使用内部字段和聚合运算符,如$cond,因此不能使用常规更新查询进行此操作,

您可以从 MongoDB 4.2 开始尝试使用 update with aggregation pipeline,

您可以在聚合更新中使用 $add 运算符来代替 $inc 您可以使用$filter 代替$pull 来删除特定用户 您可以使用$concatArrays 运算符代替$push
exports.likeIdea = (req,res,next) => 
    const userId = getUserId(req)
    Ideas.updateOne( _id: req.params.id,
      [
        $set: 
          like: 
            $cond: [
               $in: [userId, "$likedBy"] ,
               $add: ["$like", 1] ,
               $add: ["$like", -1] 
            ]
          ,
          likedBy: 
            $cond: [
               $in: [userId, "$likedBy"] ,
              
                $filter: 
                  input: "$likedBy",
                  cond:  $ne: ["$$this", userId] 
                
              ,
               $concatArrays: ["$likedBy", [userId]] 
            ]
          
        
      ]
    ).then(() => res.status(200).json( message: 'Success'))
    .catch(error => 
      res.status(400).json( error )
    );
;

Playground

【讨论】:

我从您的代码中更改了javascript [ $in: [userId, "$likedBy"] , $add: ["$like", -1] , $add: ["$like", 1] ],它就像一个魅力:) 谢谢你

以上是关于在 updateOne mongoose 方法中更新现有或使用 mongo 运算符的功能的主要内容,如果未能解决你的问题,请参考以下文章

updateOne $ set not working - Mongoose

TypeScript 中的 Mongoose post hook 类型错误

UpdateOne MongoDB 使用来自另一个字段的值进行推送

mongoose更新前修改数据库

Mongoose 报错代码 (node:10256)(node:13604)(node:13604) DeprecationWarning: Mongoose: findOneAndUpdate()

Mongoose findOneAndUpdate - 使用另一个字段更新一个字段[重复]