觀念解說 – Mongoose、schema
Mongoose
Mongoose 是 MongoDB 的 ODM(Object Data Modeling) 套件,Mongoose 套件會藉由 MongoDB driver 操作資料庫的資料
使用 ODM 通常可以降低開發和維護成本,因 ODM 會使用 JavaScript 的物件反映出資料庫中的資料,相對於使用資料庫原生的查詢語言 (SQL),用 ODM 的方式操作資料庫會更好上手
- 在專案中安裝 Mongoose1npm install mongoose --save
- 引入 mongoose 套件並連線 MongoDB 資料庫123const mongoose = require('mongoose');mongoose.connect('mongodb://localhost:27017/test');// test 為資料庫的名稱,可以改為自己的資料庫名稱
Schema
安裝 Mongoose 並連線至資料庫後,接著可以開始建立 Schema(資料庫綱要),定義需要哪些資料、型別、是否顯示、預設值…等等
例如:文件中列出 Blog 的 Schema
1 2 3 4 5 6 7 8 9 10 11 12 | const blogSchema = new mongoose.Schema({ title: String, // String is shorthand for {type: String} author: String, body: String, comments: [{ body: String, date: Date }], date: { type: Date, default: Date.now }, hidden: Boolean, meta: { votes: Number, favs: Number } }); |
當接收到資料,就可以依此 Schema 把關資料是否帶入正確
Schema 中會有需要帶入的資料屬性,title、author 等等,並會針對此資料加入相關設定,例如:型別、必填、預設…等等
type
1 | title: {type: String} // 代表 title 需為一個字串 |
若只有設定型別可以使用簡寫 title: String
若 title 是一個物件,可以針對裡面的屬性設定型別
1 2 3 4 | title: { chinese: {type: String}, english: {type: String} } |
若 title 為一個陣列,也可指定陣列中資料型別
1 | title: [{type: String}] // 若只有設定型別可以使用簡寫 [String] |
required
若此資料需為必填項目,可以設定 required,並且可客製化錯誤訊息,格式如下:
1 2 3 4 | title: { type: String, required: [true, 'title 為必填'] } |
default
若有資料未填寫,也可以設定此資料的預設值
1 2 3 4 | title: { type: String, default: '未命名的文章' } |
通常 required 與 default 不會同時使用
select
若有資料欄位希望可以被保護,不顯示出來,可以加入 select 設定
例如:若有涉及使用者相關個資 password、email …等等,都會建議加入 select: false 不將資料回傳給前端
1 2 3 4 | password: { type: String, select: false } |
enum
若此資料設定型別為 String 或 Number,可以設定 enum 指定需為哪些值
以字串為例,若 author 需為 Amy、Bob 或 Cody 其中之一,可以設定為以下:
1 2 3 4 | author: { type: String, enum: ['Amy','Bob','Cody'] } |
參考資源
– Mongoose v6.2.10: Schemas
– Mongoose v6.2.10: SchemaTypes
– Mongoose NPM 教學(可看到 Mongoose 新增 Model 流程)(章節影片)
解題
題目(將答案寫在 CodePen 並提交至回報區)
請參考以下需求,設計手搖飲的 Schema
1 2 3 4 5 | - 產品名稱(product): 需為字串,必填,若未填寫,錯誤訊息為「產品名稱未填寫」 - 價錢(price): 需為數字, 必填,若未填寫,錯誤訊息為「價錢未填寫」 - 冰塊(ice): 需為字串, 若未填寫預設為 '正常冰' - 甜度(sugar):需為字串,若未填寫預設為 '全糖' - 配料(toppings):為陣列,內容需為字串 |
1 2 3 | const drinkSchema = new mongoose.Schema({ /* 請在此填入答案 */ }); |
解答與完整程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | const drinkSchema = new mongoose.Schema({ product: { type: String, required: [true, '產品名稱未填寫'], }, price: { type: Number, required: [true, '價錢未填寫'], }, ice: { type: String, default: '正常冰', enum: ['去冰', '微冰', '少冰', '正常冰', '多冰'], }, sugar: { type: String, default: '全糖', enum: ['無糖', '微糖', '半糖', '少糖', '全糖'], }, toppings: [{ type: String }], }); |