2012-04-30 7 views
17

私のscenerioにはコレクションに著者があり、それぞれの著者はmessages、投稿者のメッセージはeventsです。各アクターは一度だけアクションを実行できます。特定のフィールドに基づいて配列内のユニークな項目を確保する方法 - mongoDB?

db.people.ensureIndex({messages.messageEvents.eventName: 1, messages.messageEvents.actorId: 1}, {unique: true}); 

インデックスを追加しましたが、効果はありません。以下に示すように、私の文書には、私の制約に反するべきである、"eventName":"vote""actorId":"1234"という3つの要素があります。

actorIdフィールドに基づいてmessageEventsの配列でユニークなアイテムを保証する方法はありますか?

実際には、拒否するのではなく、2回目の検索および更新イベントなしで既存のアイテムを更新する必要があります。

{ 
    "_id": "1234567", 
    "authorPoint": 0, 
    "messages": [ 
    { 
     "messageId": "112", 
     "messageType": "Q", 
     "messagePoint": 0, 
     "messageEvents": [ 
     { 
      "eventName": "Add", 
      "actorId": "1234", 
      "detail": "" 
     }, 
     { 
      "eventName": "Vote", 
      "actorId": "1234", 
      "detail": "up" 
     }, 
     { 
      "eventName": "Vote", 
      "actorId": "1234", 
      "detail": "down" 
     }, 
     { 
      "eventName": "Vote", 
      "actorId": "1234", 
      "detail": "cork" 
     } 
     ] 
    } 
    ] 
} 

答えて

19

Mustafa、一意の制約は、コレクション内のドキュメント間で強制されていますが、単一の配列内で強制されません。しかし、

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

回避策はあります:これは、しばらくの間、固定されることはありません既知のバグです。一意のインデックスをそのまま使用してください。

1)アプリケーションで、重複した値の新しい文書を配列に挿入しないようにしてください。挿入する前に、アプリケーションコードの一意性をチェックできます。

2)既存のドキュメントを更新するときは、$ pushの代わりに$ addToSetを使用します。

+0

あなたの答えをありがとう。あなたが正しいです。私はすでにいくつかの研究の後、私の文書表現を変更し、回避策を適用しました。私は簡単な方法があったと思う。それはコストがあり、コードが複雑になる可能性があります:( – yuceel

+1

$ addToSetを使っても、 {userId:1234、vote:obama}とプッシュされたとすると、$ addToSetは止まらない {userId:1234、vote:romney } –

+0

@OuwenHuang私は別個の質問だと思いますが、この受け入れられた答えにコメントするのではなく、個別に質問します。 –

関連する問題