How to enforce unique embedded document in mongoid How to enforce unique embedded document in mongoid mongodb mongodb

How to enforce unique embedded document in mongoid


Can't you just put a validator on the Task?

validates :name, :uniqueness => true

That should ensure uniqueness within parent document.


Indexes are not unique by default. If you look at the Mongo Docs on this, uniqueness is an extra flag.

I don't know the exact Mongoid translation, but you're looking for something like this:

db.things.ensureIndex({firstname : 1}, {unique : true, dropDups : true})


I don't believe this is possible with embedded documents. I ran into the same issue as you and the only workaround I found was to use a referenced document, instead of an embedded document and then create a compound index on the referenced document.

Obviously, a uniqueness validation isn't enough as it doesn't guard against race conditions. Another problem I faced with unique indexes was that mongoid's default behavior is to not raise any errors if validation passes and the database refuses to accept the document. I had to change the following configuration option in mongoid.yml:

persist_in_safe_mode: true

This is documented at http://mongoid.org/docs/installation/configuration.html

Finally, after making this change, the save/create methods will start throwing an error if the database refuses to store the document. So, you'll need something like this to be able to tell users about what happened:

alias_method :explosive_save, :savedef save  begin    explosive_save  rescue Exception => e    logger.warn("Unable to save record: #{self.to_yaml}. Error: #{e}")    errors[:base] << "Please correct the errors in your form"    false  endend

Even this isn't really a great option because you're left guessing as to which fields really caused the error (and why). A better solution would be to look inside MongoidError and create a proper error message accordingly. The above suited my application, so I didn't go that far.