返回
Featured image of post MongoDB - 入門

MongoDB - 入門

MongoDB - 常見的NoSQL

術語

  • database: 數據庫,對等 MySQL database
  • collection: 收藏,對等 MySQL table

快速安裝

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 步驟

  1. git clone [email protected]:neelabalan/mongodb-sample-dataset.git
  2. cd mongodb-sample-dataset && chmod +x ./script.sh
  3. brew tap mongodb/brew
  4. brew install mongodb-database-tools
  5. ./script.sh localhost 27017 root root

NodeJS 套件選擇 mongoose vs mongodb

2022年我覺得是 Typescript 的當道年,原本寫Javascript的使用者都轉型成Typescript了,之所以TS還是JS也不用多說肯定也是因為強型別問題,這也是很久的問題了,回歸主題這兩個套件選擇在2022年 我的選擇是什麼? 肯定是 mongodb

有興趣的朋友可以直接看這篇MongoDB & Mongoose: Compatibility and Comparison

有三個面相:

  1. Validation 驗證 - mongoose 在這點其實做得非常直觀但僅在應用層,mongodb用$jsonSchema在建立 Collection 直接寫在mongodb而非只是在應用層
  2. Typescript 支援 - mongoose 並不是不好,是mongodb因為 Validation $jsonSchema 是算在Option中指定的,和 mongoose是ODM所以將Schema定義的蠻複雜的
  3. Official Plugin - mongodb 官方出產,mongoose 社群力量

如果是2022年才開始碰 MongoDB的使用者,我推薦使用mongodb,當然我覺得mongoose也是一個不錯的工具,推推!


結語

在這一連串的整理MongoDB深入探討後才挖掘到它的優勢,其實關聯式資料庫 [email protected] 於2015年已經可以存JSON格式儲存,那為什麼還需要用noSQL?

  1. 關於欄位定義:

    • SQL - 必需要預建立 Table 且 column 且有必填/非必填前置設定才能寫入
    • noSQL - 不需要預建置 collection 且 column 看當時寫入狀況,只有 _id 唯一值,Key與Value皆可不同
  2. 關於Data:

    • SQL - 非必填欄位在獲取Data時,若Value為空值或非必填,皆可回傳Key: 空值
    • noSQL - 在迭代過程若先前Data無其column,無Key也無Value
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus