当嵌入式数组对象更改时,Mongoose 实例 .save() 不起作用

Posted

技术标签:

【中文标题】当嵌入式数组对象更改时,Mongoose 实例 .save() 不起作用【英文标题】:Mongoose instance .save() not working when embedded array object changed 【发布时间】:2018-04-17 19:52:43 【问题描述】:

我正在使用 Mongoose npm 模块来管理 mongodb。 这是我要更新的 mongodb 集合的架构。

var UserSchema = new Schema(
    username: 
        type: String,
        unique: true,
        required: true
    ,
    email: 
        type: String,
        unique: true,
        required: true
    ,
    cards: []
);
module.exports = mongoose.model('User', UserSchema);

在 post 请求中,这里 req 是 post 请求的请求对象。 res 是响应对象。

User.findById(userID).exec(function (err, doc) 
        let cardInfo = req.cardInfo
        let cardIndex = req.cardIndex
        doc["cards"][0] = cardInfo;
        console.log(doc)
/*  here I got right doc object as I requested

        "_id": "59f3bdd488f912234fcf06ab",
        "email": "test@gmail.com",
        "username": "test",
        "__v": 2,
        "cards": [
            
                "testNo": "42424242424242"
            
        ]
    
*/
        doc.save(function (err) 
          if (err) 
            return res.json(
              success: false,
              msg: 'Card add error'
            );
          
          res.json(
            success: true,
            msg: 'Successful updated card.'
          );
        );
)

我收到消息“更新卡成功。”,但实际上,它没有保存。 如何解决它。谢谢。

【问题讨论】:

cardIndex 在哪里使用? 用于数组卡片的索引。但我缩写为简单。没问题,当我使用参数 cardIndex = 0 发布请求时它不起作用 【参考方案1】:

问题是猫鼬不知道你的数组被修改了。

您可以使用两种解决方案:

标记已修改

This function 将嵌入元素标记为已修改并强制重新保存它。 它会告诉猫鼬重新保存这个元素。

User.findById(userID).exec(function (err, doc) 
        let cardInfo = req.cardInfo
        let cardIndex = req.cardIndex
        doc["cards"][0] = cardInfo;
        console.log(doc)
/*  here I got right doc object as I requested

        "_id": "59f3bdd488f912234fcf06ab",
        "email": "test@gmail.com",
        "username": "test",
        "__v": 2,
        "cards": [
            
                "testNo": "42424242424242"
            
        ]
    
*/
        doc.markModified('cards');
        doc.save(function (err) 
          if (err) 
            return res.json(
              success: false,
              msg: 'Card add error'
            );
          
          res.json(
            success: true,
            msg: 'Successful updated card.'
          );
        );
)

使用完整架构。

为避免 markModified 技巧,您应该在架构中描述卡片的内容。这样 mongoose 将能够确定是否需要保存该字段。

这是正确声明架构的方法:

const CardSchema = new Schema(
  testNo: String,
);

var UserSchema = new Schema(
    username: 
        type: String,
        unique: true,
        required: true
    ,
    email: 
        type: String,
        unique: true,
        required: true
    ,
    cards: [CardSchema]
);
module.exports = mongoose.model('User', UserSchema);

这样,mongoose 将能够检测卡片中的值是否更改并仅保存修改后的项目。

如果你能做到(静态模式),这显然是一个好方法。

【讨论】:

【参考方案2】:

如果你只是想根据cardIndex更新卡片:

User.update(_id: userID, '$set': 
    'cards.cardIndex': cardInfo
, function(err) 
   //code

【讨论】:

谢谢,但我必须更新现有的卡片。所以我通过了卡片索引。【参考方案3】:

感谢所有回答。 我还找到了这个解决方案。

doc["cards"].set(cardIndex, cardInfo)

干杯!

【讨论】:

以上是关于当嵌入式数组对象更改时,Mongoose 实例 .save() 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Mongoose 的嵌入式文档中检索数组的最后一个对象?

Mongoose 为啥要添加空白数组?

如何在 Mongoose 中更改文档子数组的对象内的布尔值?

推入 mongoose 对象内部的数组

MongoDB/Mongoose - 仅当某个字段是唯一的时才将对象添加到对象数组中

如何在不选择模式配置参数的情况下使用 mongoose 在 MongoDB 模式实例化中的关联数组/对象中执行 foreach?