【问题标题】:document wont save using save() method with mongoose文档不会使用带有 mongoose 的 save() 方法保存
【发布时间】:2019-01-06 17:37:15
【问题描述】:

我有这个架构:

var UserSchema = mongoose.Schema({
    analytic: {
      type: Object, 
      default: {
        today:[],
        weekly:[],
        monthly:[],
        yearly:[],
        allTime:[]
      }
    }
});

let User = mongoose.model("bloger", UserSchema);
module.exports = {User};

我正在尝试将一些数据保存到其中一个数组中,如下所示:

    User.findOne({username:username}, (e, user) => {
        if (e) {
            res.send('error fetching post')
        }
        else if (!user) {
            res.send('no user found')
        }
        else if (user) {
            user.analytic.today.push(req.body.visitor) // push the data object to the array
            user.save((e, doc) => {
                if (e) {
                    res.send(e)
                } 
                if (doc) {
                     console.log('user saved')
                    res.send(doc)
                }
            })
        }
    })
}) 

我在save() 上得到doc 对象,而不是e,所以我虽然应该保存它,但它没有。

【问题讨论】:

    标签: javascript node.js mongodb mongoose


    【解决方案1】:

    在此之前我遇到过类似的问题,因为我没有定义新模型,我只是传递了一个 JSON 对象。

    您需要创建一个新模型并保存它,而不是保存对象。

    尝试创建一个新模型,如下所示将保存传递给它;

    var newUser = new User(user);
    newUser.save((e, doc) {
        if (e) {
           res.send(e)
        } 
        if (doc) {
            console.log('user saved')
            res.send(doc)
        }
    });
    

    确保在脚本中需要用户模型。

    【讨论】:

    • 成功了,谢谢。奇怪的是,我有这么多文档使用我发布的方法,而且效果很好。 Idk 为什么它现在会发生,但是.. 好吧,至少有一个解决方案
    【解决方案2】:

    对不在您的架构中的对象进行深度修改会使 Mongoose 忽略这些更改,从而阻止它知道要保存什么(以及进行有效的原子更新)。最终结果是,当调用.save 时,Mongoose 认为没有任何修改,因此什么也不做。

    在您的特定场景中,您有两种选择:

    1。将您的 analytics 子数组添加到您的架构中

    这是最好的选择,可以更好地控制一切:

    const UserSchema mongoose.Schema({
      analytic: {
        today: [{}],
        weekly: [{}],
        monthly: [{}],
        yearly: [{}],
        allTime: [{}],
      }
    });
    

    有了这个,这些数组现在已经被 Mongoose 知道了,一切都应该正常工作了。

    请注意,在这种情况下您不需要默认值,因为 Mongoose 足够聪明,可以根据需要创建数组。

    2。手动将修改的对象标记为已修改

    如果出于某种原因您不想或无法修改架构,您可以手动将 analytic 对象标记为已修改,以便 Mongoose 知道:

    user.analytic.today.push(req.body.visitor) // push the data object to the array
    user.markModified('analytic'); // mark field as modified
    user.save(...);
    

    这会向 Mongoose 发出 analytic 或其任何子代已更改的信号,并在调用 .save 时触发更新。但请注意,Mongoose 将此视为对象的完整更改,而使用选项 1 它可以改用 $push

    【讨论】:

    • 我刚刚尝试了您的解决方案,效果很好。使用此方法是否有任何性能优势或任何其他优势?
    • @obiwankenoobi 一般来说,我知道没有性能影响。方法 1 不太可能导致竞争条件引起的问题,而方法 2 和另一个答案可能在同一用户中可能会受到某些竞争条件的影响并行更新,但我并不完全当然。
    猜你喜欢
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 2014-04-07
    • 2018-11-19
    • 1970-01-01
    • 2016-03-17
    相关资源
    最近更新 更多