20

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

1 Answer 1

26

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your answer. You are right. I have already changed my document representation and applied workaround after a few research. I wish there were easy way. It has cost and it can cause code complexity :(
Even with $addToSet, lets say we had something pushed in as {userId: 1234, vote: obama}, $addToSet would not stop {userId: 1234, vote: romney}, how would you make sure that the object set enforces uniqueness on userId only?
@OuwenHuang I think that's a separate question, I would ask it separately instead of commenting on this accepted answer.
@A.JesseJiryuDavis any chance you could update this answer for 2017.
This is a known bug that won't be fixed for a while: jira.mongodb.org/browse/SERVER-1068

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.