Mongoose 是什麼 快速掌握 Mongoose 實現 MongoDB 資料操作與 API 整合

me
林彥成
2019-09-07 | 3 min.
文章目錄
  1. 1. Mongoose 觀念與名詞
    1. 1.1. 什麼是 ODM/ORM?
  2. 2. 三步驟從資料庫到 API
    1. 2.1. Mongo DB 資料庫設定
    2. 2.2. Mongoose Schema 設計
    3. 2.3. Mongoose ODM 資料操作
  3. 3. Mongoose 專案架構

Mongoose 是一款強大的 ODM (Object Data Model) 工具,專為開發者設計,旨在簡化 MongoDB 資料庫的操作與連接。在後端開發中,Mongoose 扮演著 MongoDB 的「前端介面」角色,讓我們能夠以更直觀的方式管理資料,並透過 npm 輕鬆安裝使用。本文將帶您深入了解 Mongoose 的核心概念與實務應用。

Mongoose 觀念與名詞

Mongoose 提供了 schema-based 的解決方案,讓我們能直接操作 MongoDB 資料。在透過 Mongoose 操作資料庫時,有幾個關鍵名詞需要先有概念:

  1. Schema:定義資料庫模型結構的檔案,是 Mongoose 的核心。
  2. Model:由 Schema 當作參數產生的實例 (instance),可用來執行實際的資料庫操作。
  3. Collection:在 MongoDB 中的集合,等同於關聯式資料庫中的「表」。

什麼是 ODM/ORM?

由於像 Express 這類 Backend 框架無法直接操作資料庫,所以我們需要將資料表示為 JavaScript 的 Object,再透過 ODMORM 工具定義的資料 Schema 去操作資料庫。透過 Mongoose 就能有效達成操作 MongoDB 的目的。ODM/ORM 通常可以降低開發及維護成本,因此一般情況下都推薦使用。

  • ODM (Object Data Model):主要對應 NoSQL 資料庫,如 MongoDB
  • ORM (Object Relational Model):主要對應 SQL-Based 資料庫。

三步驟從資料庫到 API

透過 Mongoose 串接 MongoDB 並提供 API 服務,大致可分為以下三個步驟:

  1. MongoDB 資料庫設定
  2. Mongoose Schema 設計
  3. Mongoose ODM 資料操作

Mongo DB 資料庫設定

最常用的就是運用 Mongoose 搭配 MongoDB

  1. 在安裝完 Mongo 後,進入 shell 去連線看看 mongo --port 27017
  2. 成功連線後可以選擇資料庫開始下指令,像是 use test
  3. 進入 test 中設定使用者及權限:
1
2
3
4
5
6
db.dropAllUsers();
db.createUser({
user: "test",
pwd: "test",
roles: [{ role: "readWrite", db: "test" }],
});
  1. 資料庫為了安全起見會要將資料庫的 authorization 打開,windows 請參考連結,ubuntu 請去編輯 etc 資料夾底下的 Mongo 設定,加入設定如下:
1
2
security:
authorization: enabled

Mongoose Schema 設計

要使用 Mongoose 操作 MongoDB 的第一步就是要從定義 Schema 開始。定義完成後,Schema 會自動對應到 MongoDB 中的一個 collection。另外,因為不像傳統資料庫那樣有 join 的概念,所以拿資料的時候可以依照我們的使用情境去設計,像是以撈取為主的話就可以透過雙向參照的設計去加速。詳細可以參考MongoDB Schema 設計指南,分類有以下幾種:

  • Modeling One-to-Few 少量級關聯模式 (Embedding)
  • One-to-Many 多量級關聯模式 (Child-Referencing)
  • One-to-Squillions 海量級關聯模式 (Parent-Referencing)
  • Two-Way Referencing (雙向參照設計)
  • 多對一反正規化 (Denormalizing from Many -> One)

Mongoose ODM 資料操作

Mongoose 則協助我們在 Node.js Backend 專案中操作 MongoDB。在程式中定義好 Schema(不需要手動開啟欄位),確認資料庫連線沒有問題就可以直接開始操作了。

比較大的問題是 Node.js 不像 C#.net 那樣的語言有工具可以自動產生程式碼和架構,所以這個部分就是看每個人的狀況去放置,但還是以關注點分離的概念為主:

  1. 建立跟 MongoDB 的連線
1
2
3
4
5
6
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/test", {
useNewUrlParser: true,
useUnifiedTopology: true,
// ... 其他選項
});
  1. 在 model 中定義 Schema 並創造一個 Model
1
2
3
4
5
6
7
8
9
10
/**
* user model
*/

const userSchema = mongoose.Schema({
id: String,
// ... 其他欄位
});

module.exports = mongoose.model("user", userSchema);
  1. 使用剛剛產生的 Model 實例在 controller 中撈資料
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* user controller
*/

const getUser = (id) => {
return new Promise((resolve, reject) => {
const User = require("./model");
User.findOne({ id }).exec((error, docs) => {
if (error) return reject(error);
resolve(docs);
});
});
};
  1. 透過 route 開 API 給前端使用
1
2
3
4
5
6
7
8
9
10
const express = require("express");
const app = express();
app.get("/api/v1/user", async (req, res) => { // 使用 async/await 處理 Promise
try {
const user = await getUser("defaultID");
res.json(user);
} catch (error) {
res.status(500).json({ message: error.message });
}
});

Mongoose 專案架構

通常 Mongoose 會搭配一個 Backend 框架來做使用,像是 Express 或是 Koa 等等。在網路上常見的專案架構有兩種:

  1. 第一種是依照資料表去做區分,把同個資料表的 Model、controller、route 集中存放,這種方式覺得較適合大型專案。
1
2
3
4
5
6
7
8
9
10
11
├── src/
│ ├── entities/ # 按照資料表去區分
│ │ └── user/ # 使用者表
│ │ ├── model.js # Schema 定義
│ │ ├── controller.js # 資料庫 CRUD
│ │ └── route.js # API 設定
│ └── index.js # 入口
├── .eslintrc # ESLint 設定檔
├── package-lock.json
├── package.json
└── README.md
  1. 第二種則是依照功能性,controller、routes、models 集中放置在各自的分類資料夾,這種方式覺得較適合小型專案。
1
2
3
4
5
6
7
8
9
├── src/
│ ├── controller/ # 資料庫 CRUD
│ ├── routes/ # API 設定
│ ├── models/ # Schema 定義
│ └── index.js # 程式入口
├── .eslintrc # ESLint 設定檔
├── package-lock.json
├── package.json
└── README.md

喜歡這篇文章,請幫忙拍拍手喔 🤣