Mongoose save 失效?

  • 2019-05-17
  • 1,078
  • 28
  • 6

喜欢踩坑的冷月又踩到了新坑

发现问题

原有的代码简化后长这样

let resp = await schema.billing.findOne({"user": uid});
resp.billing[i].remain = parseInt(remain);
await resp.save();

没毛病对不对, await resp.save() 正确返回了doc, 没有抛出任何exception

但是, mongodb里的信息却一直 没有修改

行吧, 我们先检查下代码, 嗯 没有问题???

解决问题

一番搜索发现有很多同样遭遇的朋友

https://stackoverflow.com/questions/35733647/mongoose-instance-save-not-working/55739214

好了, 他们的方案是这样的

club.members[index].name = new_name;
club.markModified('members');
club.save();

我也试着跟着做修改

let resp = await schema.billing.findOne({"user": uid});
resp.billing[i].remain = parseInt(remain);
// 千万 千万 一定 不要删除下面这行代码, 不然马上飞天
resp.markModified('billing');
await resp.save();

改成这样后, 数据成功保存了

一个不寻根究底的程序员, 不是好的程序员, 我们来寻找这个错误的原因

为什么会发生这种情况

https://mongoosejs.com/docs/schematypes.html

在官方文档中, markModified 多用于对象内部变换 等 无法被hook的场景

但是一个简单的字典肯定可以被hook, 况且也没有特别多人反馈这个问题 (这应该是个很普及的问题), 这应该是我们的问题

回头看我们的定义

const Billing = new mongoose.Schema({
    billing: {}
}, {collection: "xxxxxx"});

难道是我定义不完全?

尝试修改billing定义

const orderSchema = new mongoose.Schema({
    remain: Number
});

const Billing = new mongoose.Schema({
    billing: [orderSchema]
}, {collection: "xxxxxx"});

好的, 现在代码正常了, 我们不需要额外 markModified 了

总结

数据结构定义不完整, 不规范可能导致hook实效

对于key不确定的数据, 我们可以 markModified

对于key固定的数据, 我们应该定好数据格式, 让他更加规范

评论