2014-11-03 52 views
3

我想測試是否更新的「upsert」選項是好的。所以我用相同的鍵「插入」一個對象到MongoDB中兩次。但它沒有顯示插入的消息。我錯過了什麼嗎?貓鼬確定update-upsert正在插入或更新

(MongoDB的:V2.6.3;貓鼬: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)可以是原始文檔。

回答

5

在貓鼬中的.update()方法需要三個參數來回調,即errnumAffectedraw響應。使用「原始」的對象,看看發生了什麼:

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及以上使用批量操作的新寫結果的反應形成:

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()方法通常用於批量操作,因此不會返回文檔內容。

+0

我剛剛完成測試.findOneAndUpdate和是的,它顯示了我想要什麼,你提到了什麼。我仍然可以使用.update()來實現相同的目標。但是.findOneAndUpdate是這種情況下最好和最簡單的方法。非常感激。 – Kevin 2014-11-03 06:41:19

+1

@Kevin'.findOneAndUpdate()'實際上並沒有告訴你是否有「插入」的內容。尤其是使用「新」選項集(這是貓鼬的默認選項)。你只能通過'「new」來判斷:false,並從那裏開始向後工作。 – 2014-11-03 06:47:17

+0

我應該說使用選項{upsert:ture,new:false}使用.findOneAndUpdate()。只是一個.findOneAndUpdate()調用仍然會讓答案混淆。感謝提醒! – Kevin 2014-11-03 07:09:34