術語
database
: 數據庫,對等 MySQLdatabase
collection
: 收藏,對等 MySQLtable
快速安裝
docker-compose
version: '3.9'
services:
mongodb:
container_name: mongodb
image: mongo
restart: always
ports:
- 27017:27017
volumes:
- ./db:/data/db
- ./bin/mongo-init.sh:/docker-entrypoint-initdb.d/init.sh
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: root
MONGO_INITDB_DATABASE: sample
MONGO_USERNAME: username
MONGO_PASSWORD: password
networks:
- sample
mongo-express:
container_name: mongo-express
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: root
ME_CONFIG_MONGODB_URL: mongodb://root:root@mongodb:27017/
networks:
- sample
networks:
sample:
/bin/mongo-init.sh
mongosh --port 27017 --authenticationDatabase -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" <<EOF
use admin
db.createUser({
user: process.env.MONGO_USERNAME ,
pwd: process.env.MONGO_PASSWORD ,
roles: [{
role: 'readWrite',
db: process.env.MONGO_INITDB_DATABASE
}]
})
EOF
快速啟用
$ docker-compose up -d
nodejs - Typescript
Install plugin
$ npm i mongodb dotenv
$ npm i -D ts-node typescript nodemon
- mongodb - mongodb client 端口
- typescript - Typescript
- ts-node - 執行Typescript 使用
- nodemon - node 啟動程式,偵測更新使用
- dotenv - 環境變數使用
攥寫時版本
package script
"scripts": {
"start": "nodemon src/index.ts"
},
.env
MONGO_USERNAME=username
MONGO_PASSWORD=password
MONGO_DB=sample
MONGO_DB_COLLECTION=sample-table
MONGO_HOST=127.0.0.1
MONGO_PORT=27017
連線
/src/index.ts
require('dotenv').config()
import { MongoClient, MongoClientOptions } from 'mongodb';
let URI = `mongodb://${process.env.MONGO_HOST}:${process.env.MONGO_PORT}`;
let DB = process.env.MONGO_DB;
let option: MongoClientOptions = {
auth: {
username: process.env.MONGO_USERNAME,
password: process.env.MONGO_PASSWORD,
},
authSource: DB,
};
// 建立 MongoClient
const client = new MongoClient(URI, option);
let main = async () => {
// 連線
await client.connect();
console.log('Connected successfully to server');
return 'done.';
};
main()
.then(console.log)
.catch(console.error)
.finally(() => {
// 中斷連線
client.close()
});
- new MongoClient() - 建立 MongoClient
- MongoClient.connect() - 連線
- MongoClient.close() - 中斷連線
MongoClientOptions
- MongoDB 重要連線設定
auth.username: 使用者帳號
auth.password: 使用者密碼
透過 Database 並指定 Collection
// 略...
interface Book {
name: string
author: string
}
let main = async () => {
await client.connect();
const database = client.db(DB);
const bookCollenction: Collection<Book> = database.collection<Book>('book');
return 'done.';
};
// 略...
- MongoClient.db() - 指定 Database
- Db.collection() - 指定 Collection
CRUD - 新增/查詢/修改/刪除
DB操作 - Google關鍵字: query
C - create
Google關鍵字: insert / 新增
R - read
Google關鍵字: find / 查詢
U - update
Google關鍵字: 修改 / 更新
D - delete
Google關鍵字: drop / 刪除
SampleData
因為官方的MongoDB SampleData,需要搭配Atlas,這邊提供一個local的方式
Insert 步驟
git clone [email protected]:neelabalan/mongodb-sample-dataset.git
cd mongodb-sample-dataset && chmod +x ./script.sh
brew tap mongodb/brew
brew install mongodb-database-tools
./script.sh localhost 27017 root root
NodeJS 套件選擇 mongoose
vs mongodb
2022年我覺得是 Typescript 的當道年,原本寫Javascript的使用者都轉型成Typescript了,之所以TS還是JS也不用多說肯定也是因為強型別問題,這也是很久的問題了,回歸主題這兩個套件選擇在2022年 我的選擇是什麼? 肯定是 mongodb
。
有興趣的朋友可以直接看這篇MongoDB & Mongoose: Compatibility and Comparison
有三個面相:
- Validation 驗證 -
mongoose
在這點其實做得非常直觀但僅在應用層,mongodb
用$jsonSchema在建立 Collection 直接寫在mongodb
而非只是在應用層 - Typescript 支援 -
mongoose
並不是不好,是mongodb
因為 Validation $jsonSchema 是算在Option中指定的,和mongoose
是ODM所以將Schema定義的蠻複雜的 - Official Plugin -
mongodb
官方出產,mongoose
社群力量
如果是2022年才開始碰 MongoDB的使用者,我推薦使用mongodb
,當然我覺得mongoose
也是一個不錯的工具,推推!
結語
在這一連串的整理MongoDB深入探討後才挖掘到它的優勢,其實關聯式資料庫 [email protected]
於2015年已經可以存JSON格式儲存,那為什麼還需要用noSQL?
關於欄位定義:
- SQL - 必需要預建立 Table 且 column 且有必填/非必填前置設定才能寫入
- noSQL - 不需要預建置 collection 且 column 看當時寫入狀況,只有
_id
唯一值,Key與Value皆可不同
關於Data:
- SQL - 非必填欄位在獲取Data時,若Value為空值或非必填,皆可回傳Key: 空值
- noSQL - 在迭代過程若先前Data無其column,無Key也無Value