# 🏅 Day 6 - Mongoose、Schema
### Mongoose
Mongoose 是 MongoDB 的 ODM(Object Data Modeling)套件,Mongoose 套件會藉由 MongoDB driver 操作資料庫的資料。
使用 ODM 通常可以降低開發和維護成本,因 ODM 會使用 JavaScript 的物件反映出資料庫中的資料,相對於使用資料庫原生的查詢語言 (SQL),用 ODM 的方式操作資料庫會更好上手。
引入 Mongoose 並連線至 MongoDB 資料庫
> 使用前需先安裝 `npm install mongooose --save`
```javascript
// 引入 mongoose
const mongoose = require('mongoose');
// 連線至資料庫
mongoose.connect('mongodb://localhost:27017/database');
// `database` 為資料庫名稱,可替換成自定義的資料庫
```
> 注意:
> 若是連線時遇到 `MongooseServerSelectionError: connect ECONNREFUSED ::1:27017` 相關錯誤,可將 `localhost` 替換成 `127.0.0.1`
> 詳細可參考:[Mongoose Connections](https://mongoosejs.com/docs/connections.html)
### Schema
綱要,定義該資料的規則:設定資料屬性、型別、是否必填、預設值 … 等等
當接收到資料,就可以依此 Schema 確認資料是否帶入正確
以訂房資訊的 Schema 為例:
```javascript
const orderSchema = new mongoose.Schema({
user: {
type: String,
required: [true, 'user is required.'],
},
userTel: {
type: String,
required: [true, 'userTel is required.'],
select: false
},
room: {
type: String,
required: [true, 'room is required.'],
enum: ['單人房','雙人房','四人房']
},
isPaid: {
type: Boolean,
default: false
},
createdAt: {
type: Date,
default: Date.now
}
});
```
以下介紹上方運用到的相關設定:
#### type
設定資料的**型別**(Number、String、Boolean ...)
`room: { type: String }`
> 若是只有設定型別,可以簡寫為 `room: String`
> 更多型別設定可觀看 [Mongoose: SchemaTypes](https://mongoosejs.com/docs/schematypes.html)
#### required
設定資料是否**必填**與客製化錯誤訊息
```javascript
room: {
type: String,
required: [true, 'room is required.']
}
```
#### default
設定資料的**預設值**(通常 required 與 default 不會同時使用)
```javascript
isPaid: {
type: Boolean,
default: false
}
```
#### select
若有資料欄位希望可以被保護,不顯示出來,可以加入 select 設定
例如:若有涉及使用者相關個資 password、email ... 等等,都會建議加入 `select: false` 不將資料回傳給前端
```javascript
userTel: {
type: String,
select: false
}
```
#### enum
若此資料設定型別為 `String` 或 `Number`,可以設定 `enum` 指定需為哪些值
以字串為例,若 room 需為 `單人房`、`雙人房` 或 `四人房` 其中之一,可以設定為以下:
```javascript
room: {
type: String,
enum: ['單人房','雙人房','四人房']
}
```
### 參考資源
- [Mongoose: Schemas](https://mongoosejs.com/docs/guide.html)
- [Mongoose: SchemaTypes](https://mongoosejs.com/docs/schematypes.html)
- 課程影音「Mongoose NPM 教學」
題目
---
請參考以下需求,設計房間的 Schema
- 房型(room): 需為字串、必填,若未填寫,錯誤訊息為「`房型為必填`」
- 定價(price): 需為數字、必填,若未填寫,錯誤訊息為「`定價為必填`」
- 最大容納人數(max):需為數字,需為「2、4、6」其中之一
- 是否含衛浴(bathroom):需為布林值,預設為 false
- 房間備品(amenities):為陣列,陣列內容需為字串
```javascript=
const roomSchema = new mongoose.Schema({
/* 請在此填入答案 */
});
```
## 回報流程
將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔!
解答位置請參考下圖(需打開程式碼的部分觀看)

<!-- 解答:
const roomSchema = new mongoose.Schema({
room: {
type: String,
required: [true, '房型為必填']
},
price: {
type: Number,
required: [true, '定價為必填']
},
max: {
type: Number,
enum: [2, 4, 6],
},
bathroom: {
type: Boolean,
default: false
},
amenities: [{ type: String }]
});
-->
回報區
---
<!--
將答案貼至下方表格內,格式:
| Discord 暱稱 | [CodePen](連結) |
-->
| Discord | CodePen / 答案 |
|:-------------:|:-----------------:|
| xxx | [CodePen]() |
| 苡安 | [hackmd](https://hackmd.io/@L7K9-66lSeagS28AP0_GjQ/SkF68n4lR) |
| 群嘉 | [CodePen](https://codepen.io/efzdamnp-the-lessful/pen/zYXaYZB?editors=0010)|
| YC | [CodePen](https://codepen.io/YCLu/pen/XWQEzKp) |
| ellallu0903 | [CodePen](https://codepen.io/ellallu0903/pen/eYoKmgG) |
| shuantt | [CodePen](https://codepen.io/th-tseng/pen/jORKEBV)|
| Lobinda | [CodePen](https://codepen.io/Lobinda/pen/dyLKPoq)|
| Aida | [CodePen](https://codepen.io/ada23410/pen/wvZXBYz?editors=0010)|
| Chia Pin | [CodePen](https://codepen.io/joker-cat/pen/QWPxbBB)|
| 阿旭 | [CodePen](https://codepen.io/koei-lu/pen/OJGEVqQ?editors=1010)|
| kelvinnn | [CodePen](https://codepen.io/is-lin/pen/GRLGRjd?editors=0010)|
| Theodore | [CodePen](https://codepen.io/GustavoFringgg/pen/ExJRPbL?editors=0010) |
| wei | [CodePen](https://codepen.io/Wei-the-sasster/pen/BaEVjPK?editors=0010) |
| tung030374 | [CodePen](https://codepen.io/tung__u/pen/qBwKayL) |
|cho|[CodePen](https://codepen.io/cho195/pen/eYoKdVy)|
| Hank | [CodePen](https://codepen.io/tw1720/pen/WNWypyo) |
| 羽 | [CodePen](https://codepen.io/lingling-Syu/pen/dyLKJBB?editors=0010) |
| 圈圈 | [CodePen](https://codepen.io/wjejfczn-the-bold/pen/bGJKaXg) |
| Jean | [CodePen](https://codepen.io/jeanchiang1221/pen/xxezYdo) |
| Otis | [CodePen](https://codepen.io/humming74/pen/PogaeZv) |
| Tiya | [CodePen](https://codepen.io/Tiya_blank/pen/JjVZaWv) |
| yiling4054 | [CodePen](https://codepen.io/lin010/pen/abxKaeQ) |
| ej_chuang | [CodePen](https://codepen.io/EJChuang/pen/abxKQPJ) |
| william_hsu | [CodePen](https://codepen.io/william8815/pen/ZEZRmBz) |
| Thomas | [CodePen](https://codepen.io/ThomasYeh/pen/qBwyBKm) |
| william威良 | [CodePen](https://codepen.io/snowman12320/pen/LYvBVPa?editors=1010) |
| runweiting | [CodePen](https://codepen.io/weiting14/pen/xxeJVdB) |
| Fabio20 | [CodePen](https://codepen.io/fabio7621/pen/LYvBZqj) |
| mei | [Codepen](https://codepen.io/l_umei/pen/mdgjmYR)|
| jenny7532 | [Codepen](https://codepen.io/wei-chen-wu/pen/abxjQoe)|
| 2魚 | [Codepen](https://codepen.io/ijrekmsn-the-sans/pen/RwOBvNX) |
| Henry | [Codepen](https://codepen.io/hekman1122/pen/eYojqgd?editors=0010) |
| Benson | [Codepen](https://codepen.io/nosneb83/pen/BaEOpwY) |
| zaoannihao | [CodePen](https://codepen.io/ckhwdvrx-the-solid/pen/jORvwJJ) |
| 瑀君 | [Codepen](https://codepen.io/yennnnn/pen/QWPVOxZ)|
| blp100x | [Codepen](https://codepen.io/blp100/pen/PogdvxN)|
| yoshidc | [CodePen](https://codepen.io/yoshiyyc/pen/VwNVVXw)|
| Ciel | [CodePen](https://codepen.io/nycteachen/pen/vYMQPRO)|
| albertyang3576 | [CodePen](https://codepen.io/albertyang3576/pen/ZEZZOVe?editors=0010)|
| puffy_chen | [CodenPen](https://codepen.io/TernMayDay/pen/XWwmoBo)|