Patterns to avoid item duplication in a Mongo.Collection


I have a collection where I have a combination of attributes forming a unique constraint on my collection.

An example is a client raising an order. The client use case is that if a user wants to create two orders on the same day, they have to edit the first order instead of generating a new one.

What is the best way to enforce this? Strategies I’ve thought through of so far are:

  1. Define ObjectID: The string passed to the ObjectID could be generated as the result of the values of the key columns. before any call to insert or upsert.
  • Create Additional Attribute: You can apply the SimpleSchema restriction unique: true from aldeed:schema-index to a compound attribute.
  • Extend the Mongo.Collection: Extend the default collection and then override the insert and upsert methods.
  • Roll it in Mongo: The unique restraint can be defined on a compound index natively in MongoDB and I believe can be accessed through collection.rawDatabase

I might have missed an option here, but I really dislike all of these options for various reasons. I’ve so far applied the third, but consider to move and wonder how other people address this issue.

1. Define ObjectID

I don’t like this because: The overhead for creating my own ObjectID feels wasteful and unless also applying step 3 and overriding the insert/upsert methods, it will be difficult to enforce this throughout a project with multiple developers.

2. Create Additional Attribute

To create an additional attribute again feels wasteful and also needs to be enforced. The compound keys are not immutable and may be changed for any document, so they may need to be updated - requiring me to also catch any updates.

3. Extend the Mongo Collection

Whenever I have overriden the insert, upsert and update methods for all my collections to check first if the object exists. I currently don’t handle updates this way as the up until now the attributes making up the key were immutable.

4. Roll it in Mongo

This is currently my preferred approach. The biggest downside I see is that a whole bunch of errors need to be handled when updates fail as a result of index changes.
I also wondered if someone has effectively done this in the form of a package, but could not find any.

1 Like

Note: I use Astronomy so my approach depends on that package.

I would create a method on the model that generates a unique key based on whatever attributes you need. That method is invoked immediately beforeSave and .validate()'s the record. If it’s not valid, then you have a duplicate order.

Give Astronomy a look, it’s definitely the missing data layer in Meteor. You define your schema in one place, and you get validations, etc.

I had not come across astronomy before. Thank you for pointing it out.

I had a quick look and like what I see. It also seems to nicely solve my next issue - how to add behaviour in addition to state to my model in a nice and not Meteor way.