我正在尝试使用 mongoose 将数据添加到我的 mongo 数据库中,但是很可能大部分数据已经在数据库中,只有少数字段需要更新。需要保存记录的创建时间和上次更新时间。
我第一次尝试解决这个问题包括使用 Model.save 函数,因为我的模型被称为服务器,并且数据是来自外部 http 服务的对象,它指定了数据中唯一的 _id。
var instance = new Server(data);
instance.save(function(err){
if(err)
console.log(err);
});
也是我的预存挂钩:
ServerSchema.pre('save', function(next) {
this.lastseen = Date.now();
if (!this.isNew)
return next() //if the entry isn't new, lets not change the date registred
this.registered = Date.now();
next() //Don't forget this!
})
这里的问题是,在重复 _id 上,保存阻塞,出现错误E11000 duplicate key error index...
现在这很有意义,因为 save 仅在instance
未使用 new 运算符创建文档时进行更新。
所以在我的下一次尝试中,我添加了代码来尝试查找文档,然后使用 underscore.js_.extend
将新文档与在数据库中找到的文档合并,然后将其保存到数据库中。这种方法的问题在于,它需要为正在处理的每个数据块额外调用数据库。
我的第三次尝试使用Model.findByIdAndUpdate
这个{upsert:true}
作品,就在数据库中存储数据而言,但是架构默认值并且我的pre-save
钩子没有被触发。
第四次尝试使用@aheckmann 在此要点中建议的代码:https ://gist.github.com/2764948
var server = new Server();
server.init(ping);
server.save(function(err){
if(err) {
console.log("DB Error: ",err);
return res.send('DB Error')
}
//if server approved, tell the inworld server to sync textures
if(server.approved)
res.send('success')
else
res.send('skip')
user.servers.addToSet(ping._id); //add the server to the user's list
user.save(function(err, usr){
if(err)
console.log("DB Error: ", err);
})
})
再次,pre-save
钩子没有被触发。我是否理解唯一使用钩子插入的方法是首先尝试使用 findById 查找文档?
问:
有没有一种方法可以根据主唯一键“更新”插入或更新,而不会对每个数据块进行多个数据库调用?有没有我忽略的方法或明显的事实?