0

I have a basic web app where with the following hierarchy being persisted

>User1
  >Client1
    >ID
    >Name
    >Profession
  >Client2
    >ID
    >Name
    >Profession

>User2
  >Client1
    >Favorite Meal
    >Favorite TV Show
    >Favorite Animal
  >Client2
    >Favorite Meal
    >Favorite TV Show
    >Favorite Animal

So basically, each users have clients and each user's clients have different fields that I want to persist. Under a single user, all the clients will have the same structure. So what I'm doing is persisting each user with nested clients in it's own document within a Clients collection.

What bugs me now is I do not know what design would be good for the following feature :

I want my Users to be able to change the fields that are persisted. So if I take the example above, User1 could remove the ID field if he doesn't need it anymore and replace it with anything else or simply not replace it at all.

1 - Should I allow my user to be able to modify the design or is that a bad idea from the get go ?

2 - If it is not a bad idea, how should I handle these changes when they are made? Should I simply (I know I'm referring to columns but these are my old relational habits)

  • Delete a column when a column is deleted
  • Rename a column when is is renamed
  • Add a column when it is added and let all the old entries have null as a value for this new column

Or should I create a new document every time a modification is made to the data of a user and try to move all the data that fits from the old document into the new one. Then delete the old document.

Are there any other good design patterns that could apply.

2

I have rarely seen a use case where nested documents were a valid way to go. Sooner or later, any combination of the following the problems occur:

  1. The BSON size limit of 16MB / doc is reached.
  2. Exceeding the padding size of the documents leads to frequent (costly) document migrations.
  3. The more complicated a model gets, the more complicated data manipulation gets - leading to longer maintenance and development times.

My suggestion would be to have independent user and client documents and look them from the client side. This way, a user can even have billions of clients and you still won't run into one of they mentioned problems.

Allowing the user to modify the persisted fields is pretty much a nightmare from the developers point of view. How do you display a decent input view? Or the output? You'd either have to parse the user specific structure and construct both views accordingly or you'd have to store meta information. I'd probably go with the approach to allow them to store additional fields in independent documents like this (which ironically is a use case for embedding documents ;) ):

{
  _id: new ObjectId(),
  user: owningUser,
  // If you want different fields for different customers
  customer: appliedTo,
  fields:[
    {name:"Date of Birth", type:"Date", value:ISODate("2015-05-05T03:46:00-01:00")},
    {name:"discount", type:"Float", value: 7.5}
  ]
}

This way, you'd have the user limited to some 16MB of additional data per customer and you have an idea for how to parse the data with a rather simple model. Setting indices on user and customer should make this efficient, too.

  • Thanks. Yes as I tought, I will have to rethink the "allow the user to modify the structure" part. Your suggestion is pretty good I might simply go with it. As for your proposition for how data should be organized (clients vs users) each users would have it's own document and unique ID, each clients would have it's own document too, it's unique ID and a UserId to specify which user he is bound to? This design is pretty much the classic one to many relational database design so I can apply this to this schema ? – phadaphunk Sep 13 '15 at 17:09

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.