2014-03-13 75 views
0

我有一個用戶,並在裏面我保存他評價的項目列表。MongoDB - 更改值的關鍵匹配

> db.users.findOne() 
{ 
    "_id" : ObjectId("5321985944aebf2ca6f2075f"), 
    "ratings" : [ 
     { 
      "532192d344aebf2ca6f2075e" : 0 
     }, 
     { 
      "532199d144aebf2ca6f20760" : 1 
     } 
    ], 
    "email" : "[email protected]", 
    "name" : "Joe Bloggs" 
} 

收視率形式:

{ item_id : <score> } 

的問題是,如果用戶速率在同一項目兩次(不同等級),而不是換舊人,這將增加數組的新元素。

我使用$addToSet來避免重複,但我想替換舊的評分。

我現在正在以一種複雜的方式來做這件事,有沒有更簡單的方法? (我正在使用Java,但解決方案沒有關係並不重要。)

回答

0

由於多種原因,這可能不是最好的模式設計。你會被這個更好的服務:

{ 
    "_id" : ObjectId("5321985944aebf2ca6f2075f"), 
    "ratings" : [ 
     { 
      id: "532192d344aebf2ca6f2075e", score: 0 
     }, 
     { 
      id: "532199d144aebf2ca6f20760", score: 1 
     } 
    ], 
    "email" : "[email protected]", 
    "name" : "Joe Bloggs" 
} 

至少在這樣你可以匹配的數組元素的id

雖然你的問題。 $addToSet是一個不錯的方便,但當然不能解決您的問題。它仍然可以使用,但如果你想添加一個「分數」這樣,那麼你將不得不使用(當然新模式):

var count = db.collection.find({ 
    "_id" : ObjectId("5321985944aebf2ca6f2075f"), 
    "ratings.id": "532192d344aebf2ca6f2075e" 
}).count(); 

if (count != 0) { 
    db.collection.update(
     { 
      "_id" : ObjectId("5321985944aebf2ca6f2075f"), 
      "ratings.id": "532192d344aebf2ca6f2075e" 
     }, 
     { 
      "$inc": { "ratings.$.score": 1 } 
     } 
    ); 
} else { 
    db.collection.update(
     { 
      "_id" : ObjectId("5321985944aebf2ca6f2075f"), 
      "ratings.id": "532192d344aebf2ca6f2075e" 
     }, 
     { 
      "$push": { 
       "id": newId, 
       "score": newScore 
      } 
     } 
    ); 
} 

或者在你實現語言的任何等同。

因此,$addToSet在您的情況下變得有點多餘,因爲您需要檢查以確定您的情況可能是$set還是$inc。更多的參與,但這是做到這一點的唯一方法。

0

您不應該使用$set

db.users.update({"email":"[email protected]"}, {$set:{"ratings.item_id":5}}) 

這樣,如果不存在較早的評級,則會添加新的評級。如果它已經存在,它將被更新。

注意:您需要用客戶端中的實際項目ID替換「item_id」。

+0

其實,閱讀這個問題時,會涉及更多一點。 $ set可能是正確的,或者甚至是$ inc,但是這是試圖保持一個唯一的** set **不重複的項目。 –

+0

我認爲這將工作,如果在文檔中添加/更新評分的唯一方法是使用$ set。那麼就不會有任何重複。 –

+0

閱讀我提供的答案以及再次閱讀問題,你應該看到這個地方不足。這是我給你留下評論的唯一原因。所以你可以理解這一點。 –