19

私のシーンリオでは、コレクションに著者がいて、各著者が持っていてmessages、著者の各メッセージが持つことができますevents。各アクターは、1種類のアクションのみを1回実行できました。

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

インデックスを追加しましたが、効果がありません。以下に示すように、私のドキュメントには3つの要素があり"eventName":"vote""actorId":"1234"それは私の制約に反するはずです。

とフィールドmessageEventsに基づいて配列内の一意のアイテムを確保するにはどうすればよいですか?eventNameactorId

実際、既存のアイテムを拒否するのではなく、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"
        }
      ]
    }
  ]
}
4

1 に答える 1

24

Mustafa、一意の制約は、コレクション内のドキュメント間で適用されますが、単一の配列内では適用されません。これは既知のバグであり、しばらくは修正されません。

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

ただし、回避策があります。独自のインデックスを適切に保持し、次のことを行います。

1)アプリケーションが配列に重複する値を持つ新しいドキュメントを挿入しないことを確認します。挿入する前に、アプリケーションコードの一意性を確認できます。

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

于 2012-04-30T16:05:16.873 に答える