Mongoid is an excellent ORM for using MongoDB. Its very easy to use as a replacement for ActiveRecord in Rails as it uses ActiveModel inside and offers a lot of the same functionality as ActiveRecord.
MongoDB encourages you to embed documents for contains type of relations rather than creating relations between different collections. If you want to know more about embedding versus linking I encourage you to read the MongoDB documentation on schema design.
When you use Mongoid and add uniqueness validations on an embedded document you’ll soon discover that these validations only apply to the scope of the parent document (as described in the validations documentation). In many cases that’s exactly what you want, however there may be scenarios where you want a field in an embedded document to be unique across the entire collection. In this article I’ll show you how that can be done.
Lets get started with an example:
1 2 3 4 5 6 7 8 9 10 11
The example is an order that has many order lines, where each order line has an article and a reference. Let’s say for the purpose of example that we want the reference on the order line to be unique across the entire order collection. The first thing to do to ensure the integrity of your collection is to add a unique index on the collection, you can define one on the Order model like so:
1 2 3 4 5
Note that you need to create the indexes in order to enforce them (see the Mongoid documentation on indexes).
While the index ensures the integrity of your database you you may get some unexpected behavior:
1 2 3 4 5 6 7 8 9 10
The index protects the integrity of your collection, but it doesn’t tell you that it fails to save. You can force Mongoid to immediately save to the collection like so:
1 2 3
While that works it isn’t performance or user friendly, ideally you’d want to use validations so you can define a friendlier error message and can use the standard save mechanism instead of forcing a direct write. This is actually pretty easy:
1 2 3 4 5 6 7 8 9 10
And that behaves pretty much how you’d expect:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
That’s really all there is to it :)