Now that we had a look at one-to-one and one-to-many relationships, the obvious missing thing is one-to-
many.
So let's say we have customers who can buy products,
so we're looking at orders,
a customer might buy multiple products and a product might be bought by different customers,
so one customer many products, one product many customers.
So this is a typical many-to-many relationship,
how could we model that? To say it right away,
often you'll model many-to-many relationships with references.
So let me again create a new database or join a new database,
my shop database and there, I might have products, so I'll insert a product here,
that product will have a title, let's say a book and the price 12.99.
I also will have customers, so I'll also insert a new customer into my customers collection, name Max,
age 29
and now with that, we could create an orders collection, orders to insert one order and there, we could now have
a productId and simply take that id of the product we added and we could have a customerId and take
that customer here and now we have that too. Now this would be the SQL world approach where we have
three tables in SQL and we have that join table in the middle which matches products and customers.
Now we can do a bit better in quotation marks in mongodb,
we can make it work with two tables only, so I can actually drop my orders collection,
so db.orders can be dropped,
so if you now find that, you find nothing because I've dropped that and all the data in it.
And with that dropped, I still have my products by the way, so we still have the products and we still
have the customers,
so we have these two tables,
I can now add orders without adding a third table and for that, I'll go to my customers let's say because
typically, I want to add that relation on the customer because you could say yes the product got bought
but actually customer is the active person and it's more realistic that you're fetching the orders for
a given customer than that you want to display orders for a given product
but that would be possible too and you can use that approach on both tables here.
So I'll show it on the customer and I'll simply update my customer here,
obviously you could also insert new customer with existing orders,
so I'll update the customer with $set and then add orders here as an array
and now every order could simply be an object where I have my productId and that still is the ID
I have up there,
so I use this ID down there
and then maybe something like the quantity. We could have also added that quantity to that third in-between
table earlier by the away.
So now if I do that and I find one customer, you see now we have the orders and that might look like I embed the
document because it is
but actually we're still using a reference approach here because we did not embed the product data,
we just added some metadata for the order
but I'm just referencing the product data.
So we're using a reference driven approach here and we could add the same orders array to the products
if we want to match it the other way around too,
so both is possible or either of the one like we have it here.
So now we have a many-to-many relationship with references, with two tables which would be the mongodb
way of displaying or creating such a many-to-many relationship with references.
You could also argue that you don't necessarily need to use references here,
often you will
and if that's your use case, it's fine but let's have a look at the embedded alternative and for that,
I'll update my orders array here and that will replace it,
it will not add this element,
we'll see how we can add elements to arrays later.
For now we'll replace that orders array with a new one, with a new array of documents of orders, here
I now have a title of my product because say I fetched that in my application when the order was placed,
with the price 12.99,
so I'm manually copying this so to say and a quantity too. Now if I look into my customers collection, we
do have an embedded document, this is now not a reference driven approach but I embedded the product data along
with the metadata for the order.
Now what could be a disadvantage of this approach?
A disadvantage is the data duplication,
we've got the title and price of that product in orders here and keep in mind that this user might order
this product multiple times and other users could do,
so you will probably duplicate this data a lot
and if you ever change that data, you not only need to change it in the products collection where you
store it and that is the product data which is displayed in your shop for users to buy it but you would
also have to change it in all the orders, well
or do you
and that is the reason why such an embedded approach might be fine.
Once the order was placed, even if the price changed for the product, we will not change it for the existing
orders
right,
the people don't have to pay more after they bought it,
so the price here is logged in anyways.
The title might change a bit but do we really care about this in our orders?
We might not care,
it's not going to change from a book to a T-shirt because it's still the same product in the end, it
still has its own unique ID and we would probably also store the ID along with the product here
by the way. So probably we don't care about a title change too because if it's a nice book now instead
of a book, doesn't really matter for us.
So if we have an application where we kind of take a snapshot of the data anyways, we might not worry
too much about duplicating that data because we might not need to change it in all the places where
we did duplicate it
if the original data changes and that of course highly depends on your application. For a shop and the
products and the orders,
this might make sense, in other use cases you might absolutely need
the latest data everywhere and we'll have a look at such a use case next.
But I want you to not automatically say many-to-many,
I will use a reference. Instead
think about how do you fetch your data,
how often do you change it
and if you change it, do you need to change it everywhere or might duplicates be fine?