# Mongo data modeling
## 2 ways of structuring relationships between documents
### Embedded data models
```js
// user
{
_id: ObjectId('5d6f72b128f00f5856e04703'),
username: "123xyz",
contact: { // <-- embeded
phone: "123-567",
email: "xyz@example.com"
},
access: { // <-- embeded
level: 3,
group: "dev"
}
}
```
- useful to store related information in the same record
- fewer queries will be needed to retrieve the `contact` and the `access` data
### Normalized data model (or references)
```js
// user object
{
_id: ObjectId('5d6f72b128f00f5856e04703'),
username: "123xyz",
contact_id: ObjectId('2'),
access_id: ObjectId('3')
}
// contact object
{
_id: ObjectId('2'),
user_id: ObjectId('5d6f72b128f00f5856e04703'),
phone: "123-567",
email: "xyz@example.com"
}
// access object
{
_id: ObjectId('3'),
user_id: ObjectId('5d6f72b128f00f5856e04703'),
level: 3,
group: "dev"
}
```
- useful when embedding would result in duplicating data
- to represent more complex one-to-many (or many-to-many) relationships
## Relationship types
### 1 to 1 => use embedding (and here is why)
Example: if the user has only one address
user data and address data can live as separate documents and user’s data reference can be stored into address document (or vice versa), but that means that every time we need address we will have to do an additional query to get the user data (since when we retrieve address, get just _id that represents user, not the users themselves). This gets to be a problem especially when we have to get this data quite often.
That’s why:
- in this case use embedded documents
- you will get both docs with just one query
## 1 to many => use embedding if it makes sense (and here is why)
Example: if a user has multiple addresses
In this case, if we use referencing we will have multiple address documents referencing the same user. Every time we need to know which addresses a single user has on file, we have to make multiple calls to figure that out.
A more optimal schema would be to embed the address data entities in the user document.
That’s why:
- in this case, use embedded documents so the user has an array of addresses embedded in their own document
- you will get all docs with just one query
## many-to-many => use references (and here is why)
Example: books and publishers
- every book can be published by more than one publisher
- every publisher publishes more than one book
What does this mean? The publisher (and book) information gets repeated multiple times (exactly the same data) so: 1) it’s overloading the database for no reason and 2) maintaining becomes nightmare since one, even the smallest change, requires finding every single document that has embedded this book or that author and making the update to every and each of them.
- Demo 1: just show publisher object and multiple books that have reference to that object through its _id
- Demo 2: publisher also gets an array of references to the books that they published
```js
// book 1
// ----------
{
_id: ObjectId('1'),
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
pages: 216,
language: "English",
publisher: {
name: "O'Reilly Media",
founded: 1980,
location: "CA"
}
}
// book 2
// ----------
{
_id: ObjectId('2'),
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
pages: 68,
language: "English",
publisher: {
name: "O'Reilly Media",
founded: 1980,
location: "CA"
}
}
// Make sense to have a publisher as a separate document and embed it into the book documents
// publisher
// ------------
{
_id: ObjectId('3'),
name: "O'Reilly Media",
founded: 1980,
location: "WY",
book_ids: [ObjectId('1'), ObjectId('2')]
}
// book 1
// -----------
{
_id: ObjectId('1'),
title: "MongoDB: The Definitive Guide",
author: [ "Kristina Chodorow", "Mike Dirolf" ],
published_date: ISODate("2010-09-24"),
pages: 216,
language: "English",
publisher_id: ObjectId('3') // <-- !!!
}
// book 2
// -----------
{
_id: ObjectId('2'),
title: "50 Tips and Tricks for MongoDB Developer",
author: "Kristina Chodorow",
published_date: ISODate("2011-05-06"),
pages: 68,
language: "English",
publisher_id: ObjectId('3') // <-- !!!
}
```