我想测试是否" upsert"更新选项很好。所以我" upsert"用相同的键将对象转换成mongodb两次。但它没有显示插入的消息。我错过了什么吗?
(mongodb:v2.6.3; mongoose:3.8.15)
Member.findOneAndRemove({user_id : 1},
function (err, doc) {
if (!err) onsole.log(doc ? 'deleted' : 'not found');
}); // -> deleted, make sure user_id = 1 doesn't exist
Member.update({user_id : 1},
{$set : {name:"name1"}},
{upsert : true, new : false}, // new : false, so that I can detect original doc is null then know it's a new one.
function (err, doc) {
if (!err) {
console.log(doc ? 'updated' : 'inserted')
}
}); // -> updated ? But it shoule be inserted, right ?
Member.update({user_id : 1},
{$set : {name:"name2"}},
{upsert : true, new : false},
function (err, doc) {
if (!err) {
console.log(doc ? 'updated' : 'inserted')
}
}); // -> updated, yes, no problem.
感谢您的任何提示。
============回答=============
使用.findOneAndUpdate代替.update! 此外,请确保选项为{upsert:true, new:false }, 以便回调的第二个参数(doc)可以是原始文档。
答案 0 :(得分:5)
mongoose中的.update()
方法为回调提供了三个参数,即err
,numAffected
和raw
响应。使用“原始”对象查看发生的情况:
Member.update({user_id : 1},
{$set : {name:"name1"}},
{upsert : true },
function (err, numAffected, raw) {
if (!err) {
console.log(raw)
}
});
你会看到这样的结构:
{ ok: true,
n: 1,
updatedExisting: false,
upserted: [ { index: 0, _id: 5456fc7738209001a6b5e1be } ] }
因此,创建的所有新文档始终都有n
和'updatedExisting keys available, where the second is false on upserts and true otherwise.
upserted will contain the
_ id`值。
对于n
或“numAffected”,这基本上始终是1,其中文档在传统写入关注响应下匹配。
您可以使用批量操作表单在MongoDB 2.6及更高版本中查看新的WriteResult响应:
var bulk = Member.collection.initializeOrderedBulkOp();
bulk.find({user_id : 1}.upsert().update({$set : {name:"name1"}});
bulk.execute(err,result) {
console.log( JSON.stringify( result, undefined, 2 ) );
}
在第一次迭代中你得到这样的东西:
{
"ok": 1,
"writeErrors": [],
"writeConcernErrors": [],
"nInserted": 0,
"nUpserted": 1,
"nMatched": 0,
"nModified": 0,
"nRemoved": 0,
"upserted": [
{
"index": 0,
"_id": "5456fff138209001a6b5e1c0"
}
]
}
还有一个具有相同参数的秒:
{
"ok": 1,
"writeErrors": [],
"writeConcernErrors": [],
"nInserted": 0,
"nUpserted": 0,
"nMatched": 1,
"nModified": 0,
"nRemoved": 0,
"upserted": []
}
并且文档只会被标记为“已修改”,其中某些内容实际已更改。
因此,无论如何,.update()
操作都不会返回修改后的文档或原始文档。这是.findOneAndUpdate()
方法,一个围绕基本.findAndModify()
执行原子操作的猫鼬包装器。 .update()
方法通常用于批量操作,因此不会返回文档内容。
答案 1 :(得分:1)
关于要使用.findOneAndUpdate
的原始问题的OP编辑,您现在还可以传递rawResult: true
参数,该参数返回文档以及通常从运行{{1}获得的数据},即:
.update
这应该足以回答原始问题,即知道您是插入还是插入。
我发现这组选项通常适用于使用{
updatedExisting: true,
n: 1,
ok: 1
}
:
.findOneAndUpdate