My OCD genes almost always push me hard to make things tidy. One outcome is to design my schemas so that related information are grouped together into objects and/or arrays and sometimes a “subdocument” structure is used for those data that could otherwise have been designed as a collection on its own and joined. Of course trying to avoid complex joins is almost always an istinct while working with mongodb.
I’m also very picky about the packages I use. When I pick one, I try to use it to its fullest. Otherwise, I just look at the source and copy over or recreate that functionality in my app on my own terms so that I can tweak it the way I want.
For this last app I’m working on, and it is a considerably large one, I’ve decided to bite the bullet and go all out with packages. There are a number of them in the app, but the ones I’m particularly relying on are:
- cfs gridfs
- aldeed simple schema
- aldeed collection2
- dburles collection helpers
- reywood publish composite
- matb33 collection hooks
- zimme collection behaviours
- zimme softremovable
- zimme timestampable
- mickaelfm vermongo
- ongoworks security
Now you see where I’m getting at. These are all collections/publications related. They form the backbone of the app and they need to be solid.
First things first, they are solid! Very! And I’m happy I chose them. I invested considerable time in picking them apart, making sure they will not break on me and so far, so good. I feel deep gratitude for those smart people who have created and contributed to these packages.
There is one slight problem though.
These magical packages lose their magic when it comes to nested fields of any form, be it objects or arrays. Especially the decorators like timestamps, versions etc rely on the top level fields.
I know well now by experience that Meteor’s fine grain reactivity and the DDP server diffing algorithm works on the top level fields, so I’d already developed an eye for where I should grant schemas their own collections, from this point of view.
But I was kind of caught blind sided by the fact that these packages also do rely on their input being top level fields.
Well, I kind of digested this rather quickly and made compromises where necessary. Again, so far so good.
But, today, I’ve spent the better part of my Sunday evening (I know, I know) trying to fit all these into the accounts system. I did not fail miserably, but I did fail. There are some moving parts that don’t work quite the way I want them to, due to email addresses being nested in the
emails object and the accounts system creating its own createdAt field, both of which I’ve figured out how to work around.
Well now, apart from the fact that I’ve always wished for more flexibility regarding the users schema (objectid problem being my top annoyance) this post is not about my beef with the accounts system.
It is about how we design schemas for our apps and how it may or may not come back to bite us. I want this experience to be out there for any one to read and take away anything they might consider valuable.
Of course our trade is all about trade offs and engineering is a discipline where we practice practical optimization rather than theoretical perfection.
So here is my 2¢; just double consider when you are designing schemas that contain nested fields/documents and arrays.