Search code examples
mongodbindexinguniquemongodb-query

How to ensure unique item in an array based on specific fields - mongoDB?


In my scenerio, there are authors in a collection, each author has messages and each message of author can has events. Each actor allowed to perform only one kind of action once.

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

I added index but it has no effect. As you see below, my document has three elements which have "eventName":"vote" and "actorId":"1234" that should be against my constraint.

How to ensure unique item in messageEvents array based on eventName and actorId fields ?

Actually, i need to update the existing item without a second search and update event instead of rejecting it .

{
  "_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"
        }
      ]
    }
  ]
}

Solution

  • Mustafa, unique constraints are not enforced within a single array, although they're enforced among documents in a collection. This is a known bug that won't be fixed for a while:

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

    There's a workaround, though. Keep your unique index in place, and:

    1) Ensure your application does not insert new documents with duplicate values in the array. You can check for uniqueness in your application code before inserting.

    2) When updating existing documents use $addToSet instead of $push.