不幸的是,有“很多”非常糟糕的示例建议使用.findOne(),然后修改返回的内容并使用.save() 提交回数据库。
你真正“应该”做的是:
io.on('connection', function (socket) {
socket.on('save_data', function (data) {
user.update(
{ "_id": socket.request.session.passport.user._id },
{ "$set": { "data": data } },
function(err,result) {
// react to result in callback
}
);
});
socket.on('remove_data', function () {
user.update(
{ "_id": socket.request.session.passport.user._id },
{ "$unset": { "data": "" } },
function(err,result) {
// react to result in callback
}
);
});
});
$set 和 $unset 都作用于文档的“数据”属性。
这些操作是“原子的”,会根据“修改时的当前状态”更新文档。
任何.findOne() 和.save() 示例都不是,除非您添加额外的处理并考虑“版本”。即使这样,您也可能会遇到问题。
因此,最好使用 MongoDB 的“本机”更新操作符来更改文档属性和内容,因为它们的设计考虑了对您的属性(并且仅属性)进行操作在更新语句中指定。
当然,这只是通过“设置”或删除它们来“更新”现有文档的属性。
如果您的“文档”甚至不存在,那么您可以将其修改为:
io.on('connection', function (socket) {
socket.on('save_data', function (data) {
user.update(
{ "_id": socket.request.session.passport.user._id },
{ "$set": { "data": data } },
{ "upsert": true },
function(err,result) {
// react to result in callback
}
);
});
socket.on('remove_data', function () {
user.remove(
{ "_id": socket.request.session.passport.user._id },
function(err,result) {
// react to result in callback
}
);
});
});
第一个.update() 调用使用"upsert" 修饰符“创建”一个新文档,其中一个尚不存在。 $set 操作中的任何内容也会添加到文档中,或者在文档存在的地方“更新”。典型的会话存储,虽然你可以优化它,但这是另一个问题。
在相反的情况下,.remove() 方法实际上是从集合中“删除”整个文档,而不是像之前所做的那样简单地“删除一个属性”。
因此,根据您的实际情况,这是针对数据库的多个事务的更好方法,可能会在您的“获取”和其他操作“之间”发生其他操作。