嵌套数组对象更改后,Mongoose实例的.save()方法无法工作

10
我正在使用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 在哪里被使用了? - chridam
它被用于数组卡片的索引。但我为了简便而缩写了它。 这不是问题,当我发送带有参数cardIndex = 0的请求时它不起作用。 - Nomura Nori
3个回答

19

问题在于mongoose不知道你的数组已经被修改。

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

markModified

这个函数将标记嵌入元素已被修改并强制重新保存它。它会告诉mongoose重新保存这个元素。

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就能检测到卡片中的值是否发生了变化,并仅保存修改后的项目。

如果你可以做到(静态模式),那么这显然是正确的方法。


0

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

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

谢谢,但我必须更新现有的卡片。所以我传递了卡片的索引。 - Nomura Nori

0

感谢所有的答案。 我另外找到了这个解决方案。

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

干杯!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接