What pattern to choose with given collections

Hi Guys! I have a front end background but I’m new to the databases and back end.

I like to be certain about the stuff that I work with and right now I need to structure my database and models in MongoDB.

I did read a lot of MongoDB articles about data modeling and different patterns, but I can’t properly fit my application into one of them.

Let’s say I have 4 collections:

User → Artist
Item → Product

I need to have a User collection with some user specific fields like name and avatar etc. Some Users can apply to become an Artist - Artist(a new collection) also has got some artist-specific fields like music genres and so on.
Artist always has to be a User first, but a User doesn’t have to be an Artist.

The other part of my app is about the Item and Product collections. An Item might have a title and description fields. An Item can become a Product and extends Item’s fields with Product ones like price for example.

For now we have a reference between a User and an Artist and Item and Product, but obviously there will be more references regarding the app itself. A User can buy a Product and an Artist can create an Item.

So that’s just a small part of the app - there will be more collections and references in the future.
I can’t find a way to model the data I have right now and I’m a bit worried about my current approach.

For now I see two possible solutions:

  1. I leave the collections as they are right now and whenever I want to get the Product or Artist data I populate Item and User accordingly.
  2. I merge User and Arist collection into one and leave the ‘artist’ fields empty as long as the User isn’t an artist. I do the same thing with Item and Product - I merge them into one collection and leave the ‘product’ related fields empty when creating a Item document and populate the fields if necessary.

My thoughts on both of those solutions:
First solution forces me to use populate(I use mongoose) or aggregate to join the collections whenever I need the data from both collections - Item & Product and User & Artist which results in having two queries. This might not be the best solution in terms of a performance, but I’m not sure if that will be the case.
Second solution feels weird for me - why should I have an empty fields on a merged collection when I don’t need them? I believe this approach will be more optimised cause I need to do just one query instead of two, but I have to say that the first solution feels more ‘natural’ for me.

Is any of those two solutions any good? Or should I find a different path? Should I be worried about joining the collections?

Thanks in advance, I really appreciate any help!

Hi @M0ngo_newbie, welcome to the community :wave: .
First of all, thank you so much for describing your concern in detail.

That’s correct, there is a performance overhead for joining two collections.

As per our Data Modelling guide:

Embedded data models allow applications to store related pieces of information in the same database record. As a result, applications may need to issue fewer queries and updates to complete common operations.

The second solution suggested by you seems correct with a small modification as follows:
Suppose your current User document looks something like this:

{
  "name": "Sourabh",
  "avatar": "https://avatars0.githubusercontent.com/u/5718?v=4",
  "email": "sourabh@example.com"
  ...
}

Therefore, to accommodate Artist specific details in your User collection, your User document would have the following structure:

// The following User is an Artist
{
  "name": "Sourabh",
  "avatar": "https://avatars0.githubusercontent.com/u/5718?v=4",
  "email": "sourabh@example.com",
  "isArtist": true,
  "genres": ["Rock", "Pop", "Jazz"],
  "awards": ["Best Rock Band", "Best Jazz Band", "MORE"]
  ...
}

// The following User is not an Artist
{
  "name": "Sourabh",
  "avatar": "https://avatars0.githubusercontent.com/u/5718?v=4",
  "email": "sourabh@example.com",
  "isArtist": false
  ...
}

Now if you would like to search for more Artists in your database, you can do so by using the following command:

db.users.find({isArtist: true})

Also, the same would be applicable for the Items document, instead of having Items and Products together, you can simply combine them in a single Product collection.

{
  "title": "MongoDB Tshirt",
  "description": "A black MongoDB Tshirt having a neon green logo printed in the front and white in the back.",
  "isListed": false,
}

{
  "title": "MongoDB Tshirt",
  "description": "A black MongoDB Tshirt having a neon green logo printed in the front and white in the back.",
  "isListed": true,
  "price": 10
}

Having said that, schemas are generally dependent on the application use cases. So, take a look at our forever free M320: Data Modeling course, where you will:

  • Learn how to create data models for MongoDB.
  • Go over a few techniques, from a very simple process for simple schemas to more complex ones for large teams and large projects.
  • Build a solid understanding of frequent patterns to apply when modeling and will be able to apply those in your designs.

If you have any doubts, please feel free to reach out to us.

Thanks and Regards.
Sourabh Bagrecha,
MongoDB