2016-09-29 52 views
0

我有一個JSON文檔這樣MongoDB中:更新嵌套的對象,如果它存在,否則它添加

{ "_id" : ObjectId("57ed88c0965bedd2b11d5727"), 
    "refid" : 2, 
    "votes" : [ 
    { "ip" : "127.0.2.1", "rating" : 5 }, 
    { "ip" : "127.0.3.1", "rating" : 2 }, 
    { "ip" : "127.59.83.210", "rating" : 50 }, 
    { "ip" : "127.56.26.191", "rating" : 5 }, 
    { "ip" : "127.59.83.210", "rating" : 5 }, 
    { "ip" : "127.59.83.210", "rating" : 30 } 
    ] 
} 

而不是創建每個IP愚弄,我想更新發現如果記錄IP存在,或者如果不存在,則添加新條目。關於如何做類似的操作有很多問題,但沒有一個我可以找到確切的問這個簡單的問題。我試圖在Node.js中:

db.collection('ratings').update({ "refid":refid, "votes.ip":ip }, 
    { 
    $push: { votes: { "ip":ip, "rating":rating } 
    } 
}) 

但它只是不斷增加新的條目,當我從同一個IP投票。

注意:我沒有使用貓鼬。

如果我的問題過於簡單,我很抱歉,我對MongoDB很陌生。我只是想知道是否有一種很好的方法可以做到這一點,而不是以編程方式迭代「投票」中的每個記錄。謝謝!

編輯:我所要求的是目前不可能的,我在正確的下方標記了一個答案,其中包含解釋和指向MongoDB票證的鏈接以增強功能。

至於我在這裏的問題的場景,下面的代碼適用於我。我不知道它有多好或壞的表現是明智的,但它涵蓋了所有這些場景:

  • 如果記錄不存在可言,如果記錄存在創建
  • ,尋找IP,如果找到,更新評級
  • 如果記錄存在,但IP不,插入一個新的評價

作品:

db.collection('ratings').findOne({ "refid":refid }).then(function(vote) { 
    if (vote == null) { 
    newrating = {refid: refid, votes: [{ ip: ip, rating: rating }]}; 
    db.collection('ratings').save(newrating); 
    } else { 
    db.collection('ratings').findOne({ "refid":refid, "votes.ip":ip }).then(function(rate) { 
     if (rate != null) { 
     db.collection('ratings').update(
      { refid: refid, "votes.ip" : ip }, 
      { $set: { "votes.$.rating" : rating } } 
     ) 
     } else { 
     db.collection('ratings').update({"refid":refid,"votes.ip" : {$ne : ip }}, 
      { $push: { votes: { "ip" : ip, "rating" : rating, }}} 
     ) 
     } 
    }) 
    } 
}) 
+0

貌似重複這樣的:http://stackoverflow.com/questions/14527980/can-you-specify-a- key-for-addtoset-in-mongo – a0viedo

+0

就我所見,評論中的鏈接和後續問題都不包含我的場景;只有如何防止基於密鑰的更新,以及單獨如何在密鑰不存在的情況下如何添加記錄。它不包括以下情況:如果有更新,則另外添加。 –

回答

2

要插入文檔如果不存在由upsert完成,並且如果要更新條件嵌入式文檔,則需要$位置運算符。所以你需要在查詢中使用它們來實現上述功能。

但現在的MongoDB不支持與$位置操作upserting

不要使用UPSERT操作位置操作$因爲, 刀片將在插入使用$作爲一個字段名文件。

所以你想要的是不可能在一個查詢現在做,或者你可以做兩個查詢。

首先

db.collection('ratings')).update(
    {"refid":refid, "votes.ip": ip}, 
    { 
    $set: { "votes.$.rating":rating } 
    } 
) 

它返回的更新文件的數量,如果是1就很好,如果它是你需要按新的記錄0。

db.collection('ratings')).update({ "refid":refid, "votes.ip":{$ne: ip}}, 
    {$push: { votes: { "ip":ip , "rating":rating }} 
}) 

還有對位置運營商和upserting JIRA票,PLZ投票這個問題,如果你想在MongoDB中此功能。下面是它可能用此方式解決以及問題

https://jira.mongodb.org/browse/SERVER-3326

+0

謝謝。 Puneet,我將用最適合我的代碼編輯原始帖子,但將你的標記標記爲正確的答案,因爲這是一個精確的解釋,爲什麼它不可能。謝謝! –

0

也許

db.collection('ratings').update({ "refid":refid, "ip":ip }, 
    { 
     $addToSet: { votes: { "ip":ip, "rating":rating } 
    } 
}) 
0

試試這個

db.collection('ratings')).update({ "refid":refid, "votes.ip":ip , "votes.rating":{$ne: rating }}, 
    {$push: { votes: { "ip":ip , "rating":rating }} 
}) 

它會增加新的記錄,如果等級不存在對於給定的IP,並在記錄被存在給IP和評價則沒有重複的記錄添加。

0

的鏈接。這是我用於工作的一個。

拉出的匹配值,推動如下新值:

db.collection(‘ratings’).update({「refid」:refid}, 
     {$pull: {votes: {「ip": ip}}}, 
    {multi: true}); 

db.collection("ratings").update({「refid":refid}, 
    {$push:{‘votes’:{"ip":ip,"rating":rating}}}) 
相關問題