前言
node.js的出現(xiàn),使得用前端語法(javascript)開發(fā)后臺服務成為可能,越來越多的前端因此因此接觸后端,甚至轉(zhuǎn)向全棧發(fā)展。后端開發(fā)少不了數(shù)據(jù)庫的操作。MongoDB是一個基于分布式文件存儲的開源數(shù)據(jù)庫系統(tǒng)。本文為大家詳細介紹了如何用node.js+mongoose玩轉(zhuǎn)MongoDB。希望能幫到有需要的人。
由于我用Mac開發(fā),以下所有操作都是在Mac下進行。
一、 環(huán)境搭建
安裝Node.js
有 node 環(huán)境的可以跳過。
nodejs官網(wǎng)提供了 macOS 安裝包,直接下載安裝即可?,F(xiàn)在 nodejs 穩(wěn)定版已經(jīng)到了 12.11.1 。
安裝MongoDB
MongoDB 是為現(xiàn)代應用程序開發(fā)人員和云時代構(gòu)建的基于文檔的通用分布式數(shù)據(jù)庫。
上個月(9月) macOS 包管理器 Homebrew 宣布移除 MongoDB 。原因是去年10月 MongoDB 宣布將其開源許可證從
GNU AGPLv3切換到SSPL(Server Side Public License),以此回應 AWS 等云廠商將 MongoDB 以服務的形式提供給用戶而沒有回饋社區(qū)的行為,MongoDB 希望從軟件即服務上獲取收入。Homebrew 認為 MongoDB 已經(jīng)不再屬于開源范疇...
言歸正傳,由于上述原因,我們不能直接使用 brew install mongodb 來安裝 MongoDB 了。好在 MongoDB 自己維護了一個定制化的 Homebrew tap。并在 Install MongoDB Community Edition
更新了安裝步驟。
Mac下 MongoDB 的最新安裝步驟如下:
1. 首先安裝 Homebrew
Homebrew 是 macOS 的包管理器。因為 OSX 默認不包含 Homebrew brew 包,所以要先安裝,已經(jīng)安裝過的可以跳過。
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
安裝過程會有點長,終端輸出信息超過一屏,這里我只截取了頭尾兩部分。
2. 然后獲取下 MongoDB Homebrew Tap
brew tap mongodb/brew
3. 最后安裝 MongoDB CE(社區(qū)版)
brew install mongodb-community@4.2
現(xiàn)在你的 Mac 上就已經(jīng)安裝好 MongoDB 環(huán)境了。
安裝mongoose
node.js 是可以直接操作 MongoDB 的,但是通過 MongoDB 命令語法直接編寫 MongoDB 驗證、數(shù)據(jù)類型轉(zhuǎn)換和業(yè)務邏輯模版比較繁瑣。所以我們使用了 mongoose。
mongoose 是 MongoDB 的一個對象模型工具,它對 MongoDB 的常用方法進行了封裝,讓 node.js 操作 MongoDB 更加優(yōu)雅簡潔。
剛才的 node.js 和 MongoDB 都是安裝在全局環(huán)境,mongoose 則是安裝在你的項目下:
cd your-project
npm i -S mongoose
現(xiàn)在,你的開發(fā)環(huán)境就已經(jīng)全部安裝好了。
二、啟動MongoDB服務
要操作 MongoDB ,首先要啟動它。
有兩種方式啟動 MongoDB 服務:
1. 在前臺運行
mongod --config /usr/local/etc/mongod.conf
前臺運行的好處就是,可以查看一些反饋和日志,便于調(diào)試。另外如果要關閉服務,只需要在終端按 control + c 鍵即可。
2. 也可以作為 macOS 服務,在后臺運行
brew services start mongodb-community@4.2
好處是開機就自動啟動,隨時可以使用。
這種啟動方式,如果要關閉服務,可以通過
stop 命令:
brew services stop mongodb-community@4.2
現(xiàn)在,你的 MongoDB 數(shù)據(jù)庫已經(jīng)開啟了。
三、操作MongoDB
操作之前先解釋一下MongoDB和mongoose里的一些核心概念。
MongoDB
- MongoDB 中的數(shù)據(jù)記錄是一種
BSON格式的文件(BSON是一種用二進制描述的JSON文件格式)。 - MongoDB 將
文件存儲在集合中,將集合存儲在數(shù)據(jù)庫中。 - MongoDB 的數(shù)據(jù)庫、集合都不用手動創(chuàng)建。
-
集合collection: 相當于關系型數(shù)據(jù)庫中的表table。 -
文件document: MongoDB 的數(shù)據(jù)記錄單位,相當于關系型數(shù)據(jù)庫中的記錄row。
mongoose
-
schema: 在 mongoose 中,所有的東西都來源于一個schema,每個schema映射了一個 MongoDB 的集合,它定義了這個集合中的文檔的骨架。 -
model: 一個文件的構(gòu)造器,通過編譯schema得到,一個model的實例就是一個文件,model負責從 MongoDB 數(shù)據(jù)庫中創(chuàng)建和讀取文檔。
更多mongoose概念可以在mongoose guide中查閱。
數(shù)據(jù)庫操作:
1. 使用 mongoose 連接 MongoDB
在項目中創(chuàng)建 connection.js 文件
// connection.js file
const mongoose = require('mongoose');
const conn = mongoose.createConnection(
// 連接地址,MongoDB 的服務端口為27017
// dbtest是我要使用的數(shù)據(jù)庫名,當往其中寫數(shù)據(jù)時,MongoDB 會自動創(chuàng)建一個名為dbtest的數(shù)據(jù)庫,不用事先手動創(chuàng)建。
'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
可以看到打印出“打開 mongodb 連接”,并且運行一直在等待。
這說明現(xiàn)在已經(jīng)成功連接上 MongoDB 了,接下來可以開始操作數(shù)據(jù)庫了。
為了方便擴展起見,我們先對 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');
// 創(chuàng)建schema
let StudentSchema = new mongoose.Schema({
name: String,
age: Number
})
// 通過connection和schema創(chuàng)建model
let StudentModel = connection.model('Student', StudentSchema);
// 通過實例化model創(chuàng)建文檔
let studentDoc = new StudentModel({
name: 'zhangsan',
age: 20
})
// 將文檔插入到數(shù)據(jù)庫,save方法返回一個Promise對象。
studentDoc.save().then((doc) => {
console.log(doc)
})
運行:
node insert.js
為了更直觀看到操作數(shù)據(jù)庫的結(jié)果,推薦大家安裝一個數(shù)據(jù)庫可視化工具:Robo3T,下載mac版安裝即可。
點擊 Robo3T 左上角連接我們的數(shù)據(jù)庫后,可以看到 MongoDB 自動幫我們生成了數(shù)據(jù)庫和集合,并且已經(jīng)插入了一條記錄:
或者還可以直接通過Model的create方法直接插入數(shù)據(jù),返回的也是一個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 file
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
可以看到name為lisi的記錄被打印了出來。
如果想查詢整個集合:
// 不放查詢條件即查詢所有的記錄
StudentModel.find({}).then(doc => {
console.log(doc);
})
可以看到集合中的所有記錄被打印了出來。
4. 更新操作
update|updateOne|updateMany方法
新建update.js文件
// update.js file
const StudentModel = require('./StudentModel');
// update 方法接收2個參數(shù),第一個是查詢條件,第二個是修改的值
// 下面把name為lisi的記錄,將他的age修改為80
StudentModel.update({name: 'lisi'}, {age: 80}).then(result => {
console.log(result)
})
進入 Robo3T,可以看到數(shù)據(jù)被更改,切換到表格模式更加直觀:
不過在終端,提示DeprecationWarning: collection.update is deprecated. Use updateOne, updateMany, or bulkWrite instead.
意思是建議我們使用 updateOne、updateMany或者bulkWrite
update 更新查詢到的所有結(jié)果,方法已經(jīng)不提倡使用,已被updateMany替代。
updateOne 如果查詢到多條結(jié)果,只更新第一條記錄。
upateMany 更新查詢到的所有結(jié)果。
bulkWrite 提供可控執(zhí)行順序的批量寫操作。
為了代碼的健壯性,我們應該根據(jù)建議將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個參數(shù),就是查詢條件
// 下面把name為lisi的記錄刪除
StudentModel.remove({name:'lisi'}).then((result) => {
console.log(result);
});
進入 Robo3T,可以看到集合里已經(jīng)沒有name為lisi的記錄了:
在看終端的輸出,跟update類似,也提示建議使用新的方法代替。
意思是建議我們使用 removeOne、removeMany或者bulkWrite
remove 刪除查詢到所有結(jié)果,方法已經(jīng)不提倡使用,已被removeMany替代。
removeOne 如果查詢到多條結(jié)果,只刪除第一條記錄。
removeMany 刪除查詢到所有結(jié)果。
bulkWrite 提供可控執(zhí)行順序的批量寫操作。
另外,終端的輸出{ n: 1, ok: 1, deletedCount: 1 }的意思跟update的類似,就不累述了。
現(xiàn)在我們已經(jīng)成功地對 MongoDB 數(shù)據(jù)庫進行了 CRUD(添加、讀取、更新、刪除)操作。歡呼~
更多高級操作,可以到mongoose API 文檔中查閱。
四、總結(jié)
梳理一下,主要講了這些內(nèi)容:
-
node.js+MongoDB+mongoose在Mac下的環(huán)境搭建,注意使用最新的MongoDB的安裝方式。 - 在Mac下如何啟動和關閉
MongoDB服務。 - 介紹了
MongoDB和mongoose的基本核心概念。 - 使用 mongoose 連接以及增刪改查 MongoDB 操作??梢允褂?
Robo3T來更直觀地觀察數(shù)據(jù)庫。
前端也能玩轉(zhuǎn)數(shù)據(jù)庫開發(fā)。
歡迎交流~
相關網(wǎng)站:
Homebrew官網(wǎng)
MongoDB官網(wǎng)
monggose官網(wǎng)
Robo3T官網(wǎng)
macOS 包管理器 Homebrew 移除 MongoDB
--
歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處:
https://champyin.com/2019/10/10/node.js%E6%93%8D%E4%BD%9C%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B9%8BMongoDB+mongoose%E7%AF%87/
本文同步發(fā)表于:
node.js操作數(shù)據(jù)庫之MongoDB+mongoose篇 | 掘金