0

I asked this over at SO and didn't get any responses after a couple weeks, so I figured I'd try SE...

TLDR;

  1. How do I update nested objects in MongoDB when data referenced in those nested objects changes?
  2. What are the pitfalls of simply storing IDs within nested objects and having the client look up the correct value to display?

Background

I have an application that I believe could benefit significantly from using a document database (e.g. MongoDB) rather than the current SQL backend. The structure of the documents in the resulting model would have a fair bit of nesting involved (2-3 levels). The issue with this is that the contents of nested objects could potentially be updated outside of the context of the document that contains that nested object. Under a relational/normalized model, this is straightforward - whenever we update the nested object (i.e. database row), that update automatically gets pulled in via a JOIN. However, I understand that trying to do this sort of JOIN/lookup pretty much defeats the purpose of using a document database in the first place...

My fear (perhaps unfounded) is that any benefits I gain from switching to Mongo (e.g. eliminating complexities of serializing the data to/from the client, faster read/write, etc.) would be mitigated by the effort/complexity of having to find and update any document that uses an object that gets changed. I know there are ways to do this, but it seems extremely cumbersome and error-prone.

Relationships are unavoidable

To the best of my ability to sort this all out, I believe the relationships and the need to update nested data are unavoidable. Essentially, when inputting the data on the client side that would become the documents, users need to select items from a dropdown box. Some of the data in these items (e.g. the display name) will occasionally get updated. Any documents that reference these items need to be updated with whatever data the item currently contains.

Possible solution

Presently, the client receives all of the lookup tables (which populate the select boxes) as part of the application state. As such, my initial instinct is to simply store the ID (which will never change) of a reference item in the document and have the client look up the correct display value from its own state. This avoids the need to update all documents that reference a particular item and also eliminates any joins on the backend. However, I am afraid I'm missing something with this solution that could cause issues in my application down the line. The obvious thing is that this would result in a certain level of coupling between the client and the backend.

So this brings me back to my questions above:

  1. Is there a non-cumbersome/reliable way to update data in existing documents when that data references other objects that might change?
  2. Are there any pitfalls with my proposed solution of simply storing the IDs in the document and forcing the client to figure out what to show the user?
10
  • It isn't clear why you want to switch to Mongo given the disadvantages you list. Are you trying to solve a performance problem?
    – DaveG
    Oct 11 at 14:15
  • Performance is the primary consideration. It would also make the conversion between front-end and back-end a lot cleaner as I could essentially store the data in the same format on both sides.
    – gaw89
    Oct 11 at 14:17
  • Why can't both the client and backend hold the data as related objects?
    – DaveG
    Oct 11 at 14:30
  • Not sure I follow what you mean by "hold the data as related objects"?
    – gaw89
    Oct 11 at 14:42
  • your solution seems like a standard and workable one to me. The only thing i would say is use natural string keys that carry meaning rather than ints or guids.
    – Ewan
    Oct 11 at 14:53
0

Document stores are not magic, and you have two basic approaches:

  • Use embedded documents, with the advantage of a fast retrieval and a preservation of the historical values, but with all the inconveniences of denormalization, in particular the painful update if the nested data is about independent entities that need to be maintained consistent, not to speak about potential document size constraints if it's about large sets of data.
  • Use a normalized data model with nested levels containing references to independent documents, with the advantage of consistency after update, but at the cost of extra read operations to access to the referenced document (even if the access to the reference is ultra-fast, you need to have some additional code to deal with it).

In MongoDB everything is about documents. So, you have to define the access strategy to those documents and organize navigation between them. This is very different from an RDBMS, where you'd launch a large join, and let the optimizer identify the best access strategy depending on the size of the tables, indexes and the criteria used. MongoDB and relational each have advantages and inconveniences, and you need to carefully evaluate which is best for your main use before you decide to switch.

To come back to your question:

  1. Except the use of a normalized model, there is no easy way to get the updates done.
  2. Having the client do the lookup is ok. But you loose control about the evolution of the data model. Why should the dlient do this, and why not let your back-end service create an aggregated document containing the results, denormalizing on the flow?
  3. If you switch to MongoDB, you need to embrace the document logic. If you stick to the relational mindset, you might get the disadvantages of both worlds.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.