# Database Design ## Overview We continue using Mongoose and Mongo to build our database. Building schemas is creating rules of a collection that we could access documents with ease since their structure are consitent. As our app grows, we would have many collections. Some are isolated and some are relating to others. Any DBMS will give us many options create these connections and also methods access data through them. Our database could be like a temple, skyscrapper or a labyrinth... each will serve different purposes; has pros and cons. Sometimes this art form called `database architecture`. ## Discussion ### Shopping Cart Every ecommerce websites are different. Some allow user to have as many shopping cart at once as the user want. Some only allow 1 cart at a time however still keeping the history of all previous cart. We will focus on the later one. To store infomation of a cart , we need either a "field" (Embedded) or a new related "schema" (References). We talked about this in previous lesson. Now, let's recall and try your best to answer these question. Really think about this before moving to the next session. Questions : - What do we need to know about a cart? - What infomation we have to record? - What infomation could be change? - How do we change thoose infomation? - What features could be create from these infomation ## Data modelling : Relationship The key decision in designing data models for MongoDB applications revolves around the structure of documents and how the application represents relationships between data. MongoDB allows related data to be embedded within a single document. ### Embeded Embedded documents capture relationships between data by storing related data in a single document structure. MongoDB documents make it possible to embed document structures in a field or array within a document. These denormalized data models allow applications to retrieve and manipulate related data in a single database operation. For many use cases in MongoDB, the denormalized data model is optimal. ## Embeded product into cart, cart into user Here is an example of 1 user info storing cart info as one of it's field ```json { "_id": "name": , "age": , "email": , "password": , "job": , "cart": [ { "_id": , "status": , "productList": [ { "_id": , "name": , "qty": , "price": , }, { "_id": , "name": , "qty": , "price": , }, { "_id": , "name": , "qty": , "price": , } , { "_id": , "name": , "qty": , "price": , } ] }, { "_id": , "status": , "productList": [ { "_id": , "name": , "qty": , "price": , }, { "_id": , "name": , "qty": , "price": , }, { "_id": , "name": , "qty": , "price": , } , { "_id": , "name": , "qty": , "price": , } ] }, { "_id": , "status": , "productList": [ { "_id": , "name": , "qty": , "price": , }, { "_id": , "name": , "qty": , "price": , }, { "_id": , "name": , "qty": , price: , } , { "_id": , "name": , "qty": , "price": , } ] }, { "_id": , "status": , "productList": [ { "_id": , "name": , "qty": , "price": , }, { "_id": , "name": , "qty": , "price": , }, { "_id": , "name": , "qty": , "price": , } , { "_id": , "name": , "qty": , "price": , } ] }, } ``` | Pros | Cons | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Let's say want a route to get the user info and all his shopping history (carts), this process would be so easy by simply connect to `User.findById()`. The data that we receive would have everything that we need. | If we just want to get the `userName` to update profile, by go the the database and get the info of that user, we waste at least `n cart info * n product info` for that one request for name | | In case product name change, or price change, or even deleted. History of the user's cart will not be affected | But if we want the product info to be updated, we must find every changes product in every cart of every users to update it | | Delete a user, will also delete all the shopping cart at ease | As a shop owner , checking the performance (sale) of shop would be inacurate. | Everytime we design a database, no matter what method of modelling we choose we must ask our selves: - What operation will I do with this info? - How can I CRUD? Is it efficent? - If 1 field changes, what is the effect to the others? How can we accounted for all thoose changes? - Would this design sustain 10 users? 100? 1000? or even 1000,000,000,000 users? - If not, how difficult it is for changing the structure in the future? ### References References store the relationships between data by including links or references from one document to another. Applications can resolve these references to access the related data. Broadly, these are normalized data models. ## Referencing cart Here is an example of referencing data. This approach take 3 schemas and reference them with each other `_id` ### The product Given 2 products ```js { _id : "product 1", name: , price: , } { _id : "product 2", name: , price: , } ``` ### The user ```js { _id: "tuan_id", name: email: password: role: } ``` ### The cart ```js { _id: "Haha Cart", OWNER: "tuan_id" status: , productList: [ {productId: "product 1",qty: }, {productId: "product 2",qty: } ] } ``` ### Pro and cons - how to get user name ? - how to get the owner of a cart ? - how to know if an user have cart ? - how to add a product to cart ? - how delete user ? - how to check sale performance ? | Pros | Cons | | ------------ | ------------ | | Embeded'cons | Embeded'pros | ## Summary There is no magic fomular for a perfect data modelling. The answer is alway "depend" on what feature we decided for our application, commonly called **business logic**. Backend coding syntax is difficult, but the logic behind connecting data toghether to have the best way possible to solve a set of problems is what make us programmer. ### Case study : CoderComm backend Today we will start the CoderComm backend project. For the next few days we will re-create the API that we have been using for our previous React front-end application. We will be collaborating on [this repo](https://github.com/lukehoang1905/social-platform-mongo-express)