node.js操作數據庫之MongoDB+mongoose篇

前言

node.js 的出現,使得用前端語法(javascript)開發後臺服務成爲可能,越來越多的前端因此因此接觸後端,甚至轉向全棧發展。後端開發少不了數據庫的操作。MongoDB 是一個基於分佈式文件存儲的開源數據庫系統。本文爲大家詳細介紹瞭如何用 node.js + mongoose 玩轉 MongoDB 。希望能幫到有需要的人。

由於我用Mac開發,以下所有操作都是在Mac下進行。

一、 環境搭建

安裝Node.js

有 node 環境的可以跳過。

nodejs官網提供了 macOS 安裝包,直接下載安裝即可。現在 nodejs 穩定版已經到了 12.11.1

安裝MongoDB

MongoDB 是爲現代應用程序開發人員和雲時代構建的基於文檔的通用分佈式數據庫。

上個月(9月) macOS 包管理器 Homebrew 宣佈移除 MongoDB 。原因是去年10月 MongoDB 宣佈將其開源許可證從 GNU AGPLv3 切換到 SSPL(Server Side Public License),以此迴應 AWS 等雲廠商將 MongoDB 以服務的形式提供給用戶而沒有回饋社區的行爲,MongoDB 希望從軟件即服務上獲取收入。Homebrew 認爲 MongoDB 已經不再屬於開源範疇...

言歸正傳,由於上述原因,我們不能直接使用 brew install mongodb 來安裝 MongoDB 了。好在 MongoDB 自己維護了一個定製化的 Homebrew tap。並在Install MongoDB Community Edition更新了安裝步驟。

Mac下 MongoDB 的最新安裝步驟如下:

1. 首先安裝 Homebrew

Homebrew 是 macOS 的包管理器。因爲 OSX 默認不包含 Homebrew brew 包,所以要先安裝,已經安裝過的可以跳過。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

安裝過程會有點長,終端輸出信息超過一屏,這裏我只截取了頭尾兩部分。
mg-install-homebrew.jpg

mg-install-homebrew-2.jpg

2. 然後獲取下 MongoDB Homebrew Tap

brew tap mongodb/brew

mg-tap-mongodb-brew.jpg

3. 最後安裝 MongoDB CE(社區版)

brew install [email protected]

mg-brew-install-mongodb.jpg

現在你的 Mac 上就已經安裝好 MongoDB 環境了。

安裝mongoose

node.js 是可以直接操作 MongoDB 的,但是通過 MongoDB 命令語法直接編寫 MongoDB 驗證、數據類型轉換和業務邏輯模版比較繁瑣。所以我們使用了 mongoose。

mongoose 是 MongoDB 的一個對象模型工具,它對 MongoDB 的常用方法進行了封裝,讓 node.js 操作 MongoDB 更加優雅簡潔。

剛纔的 node.js 和 MongoDB 都是安裝在全局環境,mongoose 則是安裝在你的項目下:

cd your-project
npm i -S mongoose

mg-install-mongoose.jpg

現在,你的開發環境就已經全部安裝好了。

二、啓動MongoDB服務

要操作 MongoDB ,首先要啓動它。
有兩種方式啓動 MongoDB 服務:

1. 在前臺運行

mongod --config /usr/local/etc/mongod.conf

前臺運行的好處就是,可以查看一些反饋和日誌,便於調試。另外如果要關閉服務,只需要在終端按 control + c 鍵即可。
mg-run-mongodb-in-foreground.jpg

2. 也可以作爲 macOS 服務,在後臺運行

brew services start [email protected]

好處是開機就自動啓動,隨時可以使用。
mg-run-mongodb-as-a-server.jpg

這種啓動方式,如果要關閉服務,可以通過 stop 命令:

brew services stop [email protected]

mg-stop-mongodb-service.jpg

現在,你的 MongoDB 數據庫已經開啓了。

三、操作MongoDB

操作之前先解釋一下MongoDB和mongoose裏的一些核心概念。

MongoDB

  • MongoDB 中的數據記錄是一種 BSON 格式的文件(BSON是一種用二進制描述的JSON文件格式)。
  • MongoDB 將文件存儲在集合中,將集合存儲在數據庫中。
  • MongoDB 的數據庫、集合都不用手動創建。
  • 集合collection: 相當於關係型數據庫中的表table
  • 文件document: MongoDB 的數據記錄單位,相當於關係型數據庫中的記錄row

mongoose

  • schema: 在 mongoose 中,所有的東西都來源於一個 schema,每個schema 映射了一個 MongoDB 的集合,它定義了這個集合中的文檔的骨架。
  • model: 一個文件的構造器,通過編譯schema得到,一個model的實例就是一個文件model負責從 MongoDB 數據庫中創建和讀取文檔

更多mongoose概念可以在mongoose guide查閱。

數據庫操作:

1. 使用 mongoose 連接 MongoDB

在項目中創建 connection.js 文件

// connection.js file
const mongoose = require('mongoose');
const conn = mongoose.createConnection(

  // 連接地址,MongoDB 的服務端口爲27017
  // dbtest是我要使用的數據庫名,當往其中寫數據時,MongoDB 會自動創建一個名爲dbtest的數據庫,不用事先手動創建。
  'mongodb://127.0.0.1:27017/dbtest', 

  // 一些兼容配置,必須加,你不寫運行的時候會提示你加。
  {
    useNewUrlParser: true,
    useUnifiedTopology: true
   }
)
conn.on('open', () => {
    console.log('打開 mongodb 連接');
})
conn.on('err', (err) => {
    console.log('err:' + err);
})

運行:

node conection.js

mg-connection.jpg

可以看到打印出“打開 mongodb 連接”,並且運行一直在等待。

這說明現在已經成功連接上 MongoDB 了,接下來可以開始操作數據庫了。

爲了方便擴展起見,先對 connection.js 改造一下,讓它作爲模塊導出,這樣就可以在其他地方導入複用了。

// connection.js file
const mongoose = require('mongoose');
const conn = mongoose.createConnection(
  'mongodb://127.0.0.1:27017/dbtest',
  {
    useNewUrlParser: true,
    useUnifiedTopology: true
   }
)
conn.on('open', () => {
    console.log('打開 mongodb 連接');
})
conn.on('err', (err) => {
    console.log('err:' + err);
})

module.exports = conn; //commonJs 語法,導出conn模塊。

2. 添加操作

save | create
新建insert.js

// insert.js file
let mongoose = require('mongoose');

// 導入連接模塊
let connection = require('./connection');

// 創建schema
let StudentSchema = new mongoose.Schema({
   name: String,
   age: Number
})

// 通過connection和schema創建model
let StudentModel = connection.model('Student', StudentSchema);


// 通過實例化model創建文檔
let studentDoc = new StudentModel({
    name: 'zhangsan',
    age: 20
})

// 將文檔插入到數據庫,save方法返回一個Promise對象。
studentDoc.save().then((doc) => {
    console.log(doc)
})

運行:

node insert.js

爲了更直觀看到操作數據庫的結果,推薦大家安裝一個數據庫可視化工具:Robo3T,下載mac版安裝即可。
mg-robo3T-download2.jpg

點擊 Robo3T 左上角連接我們的數據庫後,可以看到 MongoDB 自動幫我們生成了數據庫和集合,並且已經插入了一條記錄:
mg-insert.jpg

或者還可以直接通過Model的create方法直接插入數據,返回的也是一個Promise:

StudentModel.create({
    name: 'lisi',
    age: 19
}).then((doc) => {
    console.log(doc)
})

3. 讀取操作

find
爲更加合理複用代碼,我們先把 StudentSchema 和 StudentModel 抽離出來:

新建StudentSchema.js

// StudentSchema.js file
const mongoose = require('mongoose');

let StudentSchema = mongoose.Schema({
    name: String,
    age: Number
})

module.exports = StudentSchema;

新建StudentModel.js

// StudentModel.js 
const connection = require('./connection');
const StudentSchema = require('./StudentSchema');

let StudentModel = connection.model('Student', StudentSchema);

module.exports = StudentModel;

然後新建query.js文件

// query.js file
const StudentModel = require('./StudentModel');

// 富查詢條件,對象格式,鍵值對,下面爲查詢 name 爲 lisi 的記錄
StudentModel.find({name: 'lisi'}).then(doc => {
    console.log(doc);
})

運行

node query.js

mg-guery.jpg

可以看到namelisi的記錄被打印了出來。

如果想查詢整個集合:

// 不放查詢條件即查詢所有的記錄
StudentModel.find({}).then(doc => {
    console.log(doc);
})

mg-guery-all.jpg

可以看到集合中的所有記錄被打印了出來。

4. 更新操作

update|updateOne|updateMany

新建update.js

// update.js file
const StudentModel = require('./StudentModel');

// update 方法接收2個參數,第一個是查詢條件,第二個是修改的值
// 下面把name爲lisi的記錄,將他的age修改爲80
StudentModel.update({name: 'lisi'}, {age: 80}).then(result => {
    console.log(result)
})

進入 Robo3T,可以看到數據被更改,切換到表格模式更加直觀:
mg-update2.jpg

不過在終端,提示DeprecationWarning: collection.update is deprecated. Use updateOne, updateMany, or bulkWrite instead.
mg-update.jpg

意思是建議我們使用 updateOneupdateMany或者bulkWrite

  • update 更新查詢到的所有結果,方法已經不提倡使用,已被updateMany替代。
  • updateOne 如果查詢到多條結果,只更新第一條記錄。
  • upateMany 更新查詢到的所有結果。
  • bulkWrite 提供可控執行順序的批量寫操作。

爲了代碼的健壯性,我們應該根據建議將update方法換成updateMany方法。

另外,終端的輸出{ n: 1, nModified: 1, ok: 1 }的意思是:

  • “n: 1”:查詢到1條記錄。
  • “nModified: 1”:需要修改1條記錄。(如果修改值和原始值相同,則需要修改的就是0條)
  • “ok: 1”:修改成功1條。

5. 刪除操作

remove|removeOne|removeMany|bulkWrite

新建remote.js

// remove.js file
const StudentModel = require('./StudentModel');

// delete 方法接收1個參數,就是查詢條件
// 下面把name爲lisi的記錄刪除
StudentModel.remove({name:'lisi'}).then((result) => {
    console.log(result);
});

進入 Robo3T,可以看到集合裏已經沒有name爲lisi的記錄了:
mg-remove2.jpg

在看終端的輸出,跟update類似,也提示建議使用新的方法代替。
mg-remove.jpg

意思是建議我們使用 removeOneremoveMany或者bulkWrite

remove 刪除查詢到所有結果,方法已經不提倡使用,已被removeMany替代。
removeOne 如果查詢到多條結果,只刪除第一條記錄。
removeMany 刪除查詢到所有結果。
bulkWrite 提供可控執行順序的批量寫操作。

另外,終端的輸出{ n: 1, ok: 1, deletedCount: 1 }的意思跟update的類似,就不累述了。

現在我們已經成功地對 MongoDB 數據庫進行了 CRUD(添加、讀取、更新、刪除)操作。歡呼~

更多高級操作,可以到mongoose API 文檔查閱。

四、總結

梳理一下,一共講了這些內容:

  1. node.js+MongoDB+mongoose 在Mac下的環境搭建,注意使用最新的 MongoDB 的安裝方式。
  2. 在Mac下如何啓動和關閉 MongoDB 服務。
  3. 介紹了 MongoDBmongoose 的基本核心概念。
  4. 使用 mongoose 連接以及增刪改查 MongoDB 操作。可以使用 Robo3T 來更直觀地觀察數據庫。

文章有點長,我寫的比較細。如果你是零基礎的人,那麼通過這篇文章完全可以獨立上手開始搗鼓MongoDB了。如果你是有這方面經驗者,歡迎提出意見,歡迎交流~

相關網站:
Homebrew官網
MongoDB官網
monggose官網
Robo3T官網
macOS 包管理器 Homebrew 移除 MongoDB

--
歡迎轉載,轉載請註明出處:
https://champyin.com/2019/10/...

本文同步發表於:
node.js操作數據庫之MongoDB+mongoose篇 | 掘金

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章