I wrote this brain-dump back in October of 2013 and am just now publishing it in 2016. As you will see, I was a bit irritated at having been forced to use Mongo in a relational way. I had warned my coworkers, architectural leadership, and the CTO (of the small embedded “startup” I was working for) repeatedly about the dangers of misusing a non-transactional NoSQL system. By the time we started to see real occurrences of non-transactional updates interfering with each other, all the other people on my team were gone or on their way out. I took it to heart that I should stand up for my technical opinions more. I’m finally publishing this post without making edits.
Oh, and a disclaimer: I haven’t used Mongoid or MongoDB since that project, so many things have probably changed. Also, all my projects that use NoSQL since then have used it properly (not relationally).
Don’t downplay the consistency issues you will encounter with MongoDB. You will encounter them at some point, and they will be difficult to resolve. Your data will become inconsistent at some point, and it may be difficult to identify the problem, identify the cause of the problem, and resolve the data. It will also be difficult to determine the proper approach you should take in your code to avoid such inconsistencies. Pay attention to those who advise using a transactional datastore as your primary source of truth to start with, and including NoSQL datastores as solutions to targeted performance problems when they appear later.
Mongoid: don’t try to build up changes in memory and validate all before saving: it’s still a piecemeal save of each individual object. Also, you’ll run into problems where you have multiple copies of the same object in memory, each with different states. Also, it’s impossible to perform a delete in-memory and validate that before actually persisting it. Instead, save each modification in turn and be careful to watch for places where .reload() will be necessary in order to see the previous modifications. Doing this is not easy.
Also see my post at: https://groups.google.com/forum/#!searchin/mongoid/shannon/mongoid/0m3i2pwjh-0/neN0HzZcmccJ
Using a “live” UI that makes a small change (ideally on a single document) for each user interaction is ideal. It’s not honest to present the user with a large edit page with a “save” and “cancel” button, as clicking “save” may result in only part of the changes taking effect. That is, unless you have written a full transaction management system on top of Mongo, in which case you’ll be tackling all the issues of concurrency that database researchers, programmers, and vendors have already addressed in mature, transactionally consistent (SQL) datastores. It’s unlikely you’ll be able to achieve performance, accuracy, and reliability equivalent to the existing transactional databases.
Achieving eventual consistency: eg. how to ensure that both ends of a many-to-many are updated? Or, how to make sure that it doesn’t matter to the reader whether they’re consistent (eg. it ignores anything that disagrees (negative impact on performance)). Ensure that anything that could be considered a denormalization is a lazy action that can be queued & attempted repeatedly??