資料庫的連結對於網頁是不可或缺的,無論是 MongoDB 或是 Django,這種 NoSQL 的資料庫構建套件都十分的受程式設計師的歡迎,由於其不用再去學 SQL 格外的構築語法,NoSQL 就成為了廣為人知的開源資料庫,最近專案正好使用到 MongoDB,本篇來介紹一下 MongoDB、MongoDB 的安裝方式,以及使用 Node.js 串接 MongoDB 的 CRUD。
MongoDB 是一種文件導向資料庫管理系統,由 C++ 撰寫而成,是一個以分散式檔案儲存為基礎的資料庫,旨在 Web 應用提供可擴充的高性能資料儲存解決方案。
Document Oriented Storage
)的資料庫,以 key:value
表示,儲存格式與 JSON 完全一樣。MongoDB 世界的層級觀念,分別由大而小:
Database (資料庫): 資料庫,儲存所有「表」跟資料的地方,在一個 MongoDB 伺服器中通常會有一至多個 Database,通常將不同的應用放在不同 database 中。
Collection (集合): 就是資料表,概念好比關聯式資料庫的 Table。通常一個 databse 中會有數個 collection。
Document (文件): 就是一筆資料,概念就如同關聯式資料庫的 Row。通常一個 collection 中會有數筆 document。也因此我們稱 MongoDB 是 document database。
關聯式資料庫(RDBMS) | MongoDB |
---|---|
Database | Database |
Table | Collection |
Tuple/Row | Document |
Column | Field |
Table Join | Embedded Documents |
Primary Key | Primary Key (如果沒有設定,mongodb會自動給予 預設主鍵值 _id 欄位) |
BSON 就是 JSON 格式的 key-value
組合,採用 JSON 的二進位表示。
MongoDB 在儲存資料時,都必須採用 BSON 格式做處理。
使用 BSON 的優點包含:
我們以網站結構範例來示範:
{
"email": "jddj4541@gmail.com",
"password": "54875487"
},
{
"email": "jddj4541@gmail.com",
"password": "54875487"
},
...
因為 MongoDB 的 schemeless 特性,當我們突然想為其中一個 user 紀錄手機,只需要在那個 user 的 document 中加入「手機」這個新欄位就行,其他 user 完全不受影響。
{
"email": "jddj4541@gmail.com",
"password": "54875487"
},
{
"email": "jddj4541@gmail.com",
"password": "54875487",
"phone": "0912345678"
},
...
實際上 BSON 支援的 type 有很多,這邊我們再舉一個包含多種 type 的 document 當作範例:
{
"_id": ObjectId("5099803df3f4948bd2f98391"), // _id 屬性是 ObjectId,常作為主鍵
"name": { "first": "Alan", "last": "Turing" }, // name 屬性是 object
"email": "jddj4541@gmail.com",
"password": "54875487",
"phone": "0912345678",
"birth": new Date('Jun 23, 1912'), // bitrh 屬性是日期
"death": new Date('Jun 07, 1954'),
"contribs": [ "Turing machine", "Turing test", "Turingery" ],
"views": NumberLong(1250000)
}
在安裝前,我們先來確認 Windows 版本。
在終端機輸入,並執行:
wmic os get osarchitecture
> OSArchitecture
> 64-bit # 顯示出所用的 OS 是哪一種結構。
接著,我們去 MongoDB Downlad Center 下載所需套件:
下載後,可以參考 Install on Windows 我們就依此文件,做以下的操作:
C:\Program Files\MongoDB\Server\6.0\
那我們這裡就依照官方的,不改。前往安裝目錄下 /bin 目錄中,會發現沒有 mongo.exe 檔案,原因在於:MongoDB 6.0 以後做出了重大改變,已經不再預設為你安裝 shell 工具,因此需要安裝一個額外的 shell:Install mongosh -- MongoDB Shell,這個工具被稱為 mongosh。
前往頁面下載 mongosh.exe,下載後將解壓縮出來的 bin 資料夾內的檔案,複製到安裝目錄下 /bin 目錄中。
直接點擊 mongosh.exe 即可進入 MongoDB shell 界面。
要執行 MongoDB Shell,還需要回到 /bin 目錄底下,無法在任意地方執行 MongoDB Shell,原因:環境變數未設定。
設定步驟:
"開始"選單點選右鍵 -> 系統 -> 進階系統設定。
點選"進階" -> 環境變數。
系統變數的 Path,點擊"編輯"。
將 C:\Program Files\MongoDB\Server\6.0\bin
加入原本字串後方!
(新版的 Windows,C:\...
前面可以不用加分號 ;C:\...
)
有安裝服務,就也有移除服務,如果你決定要移除 MongoDB 服務,可以在終端機執行:
"C:\Program Files\MongoDB\Server\6.0\bin\mongod.exe" --remove
# or
# mongod --remove
MongoDB 預設資料庫存放位置是 ${安裝目錄}\data\db
,所以我們可以建立這樣的資料庫路徑:
在 C:\
以 Command pormpt 執行:
mkdir \MongoDB\data\mydb
接著執行:
cd "C:\Program Files\MongoDB\Server\6.0\bin"
目前,我們位在 C:\Program Files\MongoDB\Server\6.0\bin >
輸入:
mongod --dbpath c:\MongoDB\data\db
啟動同時,指定資料庫存放位置!
接著,出現像這樣的畫面,表示 MongoDB 已經正常啟動了!
你就可以開始使用了!
可以參考一些文件 Getting Started 來做測試。
Note: 關於資料庫存放位置,其實可以自己設定好一個資料夾位置,指定過去就好囉!不限於一定得在 \data\db 之下!
資料庫啟動以後,我們開啟另一個終端機執行:
mongosh
# .exe 可以不用
啟動 MongoDB Shell 環境,當我們看到如圖畫面,代表連線 MongoDB 成功:
我們可以做一些簡單的查詢,比方 show dbs
可以看到底下有哪些資料庫。
要使用資料庫 TestDB,可以用 use TestDB
如圖:
exit
admin
資料庫下,使用 db.shutdownServer()
show collections
inserOne
db.rooms.insertOne(
{ name: "單人房", price: 1000, rating: 4.5 }
)
insertMany
db.rooms.insertMany(
[
{ name: "豪華單人房", price: 1500, rating: 4.3 },
{ name: "雙人房", price: 2000, rating: 4.8 },
]
)
db.collections.find()
db.<集合名稱>.find()
db.collections.find({屬性名稱:屬性值})
db.rooms.find({"name":/雙/})
db.collections.find({屬性名稱:{$lte:400}})
db.collections.find({屬性名稱:{$lte:400},rating:{$gte:4.8}})
db.rooms.find({"name":/雙/},{"_id":0})
db.rooms.find({"payment":{$in:["信用卡"]}}
運算子 | 說明 |
---|---|
$eq | 等於 |
$gt | 大於 |
$lt | 小於 |
$gte | 大於等於 |
$lte | 小於等於 |
$in | 存在某個值 |
$nin | 不存在某個值 |
or | 或 |
and | 與 |
舉個例子:
db.rooms.find(
{ $and:
[
{ price: { $lte:1500 } },
{ rating: { $gte:4.5 } }
]
}
)
replaceOne()
只能替換整個文件;updateOne()
允許更新欄位。
db.rooms.updateOne(
{
"_id": ObjectId("621edf99a20aa7506a116f9a")
},
{
$set: { name: "修改雙人房" }
}
)
修改多個值 updateMany(filter 篩選 > $set 更換設定)
db.rooms.updateMany(
{ rating: { $gt:4.5 } },
{ $set: { price:300 } }
)
replaceOne
、replaceMany
db.collection.replaceOne(filter, replacement, options)
-- 舉個例子:
db.rooms.replaceOne(
{ "_id": ObjectId("621edf99a20aa7506a116f9a") },
{ name: "yes~" }
)
deleteMany(filter)
db.rooms.deleteMany(
{ rating: { $gte:4.3 } }
)
[
{
"rating": 4.5,
"price": 1000,
"name": "標準單人房",
"payment": ["信用卡","ATM"]
},
{
"rating": 4.3,
"price": 1500,
"name": "豪華單人房",
"payment": ["信用卡","ATM"]
},
{
"rating": 4.8,
"price": 2000,
"name": "標準雙人房",
"payment": ["信用卡","ATM"]
},
{
"rating": 4.7,
"price": 2500,
"name": "豪華雙人房",
"payment": ["ATM"]
},
{
"rating": 4.0,
"price": 3000,
"name": "標準四人房",
"payment": ["現金"]
},
{
"rating": 3.5,
"price": 10000,
"name": "總統套房",
"payment": ["現金"]
}
]
help
如果,我們想要將操作 MongoDB 的記錄,寫進 log 裡。
我們先建立一個放置 log 的資料夾,為了有規律的放置檔案:
C:\MongoDB\data\db
放置 databaseC:\MongoDB\data\log
放置 log所以,建立一個資料夾 log
# 於 C:\MongoDB\data 下
mkdir log
接著,我們要建立一個 config 檔案,它是 MongoDB 的配置檔,內容可以配置 db 路徑(storage.dbPath)及 log 寫入檔案(systemLog.path)。
storage:
dbPath: C:\MongoDB\data
journal:
enabled: true
systemLog:
destination: file
logAppend: true
path: C:\MongoDB\data\log\mongod.log
net:
port: 27017
bindIp: 127.0.0.1
接著,我們以系統管理員身份啟動終端機
# 安裝設定(cfg 檔位置必須為絕對路徑,否則會報錯)
mongod --config "C:\MongoDB\data\log\mongod.cfg" --install
接著,我們就可以直接在任意位置,以簡單的方式,啟用服務,而不用每次啟動,都要指向資料庫位置。
不再用 mongod –dbpath C:\MongoDB\data\db
這一長串東西。
啟用服務:
net start MongoDB
停用服務:
net stop MongoDB
如圖:
每執行服務,都會寫一次 log 檔,在我們當初配置的資料夾。
以上,我們已經完成了 MongoDB 的安裝與執行,再來說明使用 Node.js 串接 MongoDB 做 CRUD。
這邊先著重 Node.js 概括的學習,閒有餘力,再深入 MongoDB。
關於 MongoDB 比較基礎且重要的,可以先參考:
它裡面教你如何在 MongoDB 裡新增、讀取、更新、刪除的基本資料操作。
這邊我直接參考 access-mongodb-in-nodejs 完成此篇這一系列的 Node.js 學習。
那我們開始吧!
我們需要安裝 mongodb-driver,在終端機輸入:
npm install mongodb -g
cd myapp
npm install mongodb --save
我們打開 package.json
看,安裝了 mongodb: "5.0.0"
(注意,這裡安裝的是 driver
,不是 MongoDB 喔!)
接著,我們要啟動我們的 MongoDB Server,可在終端機輸入:
# 也可以直接在 myapp 裡建一個測試的數據資料庫存放位置
mkdir testdb
mongod --dbpath c:\myapp\testdb
或是,如果已經設定好 config 的 MongoDB service,那就直接使用:
net start mongodb
註:這邊可能要用系統管理員身份執行終端機才可以正確執行!
let MongoClient = require('mongodb').MongoClient;
// Connect to the db
MongoClient.connect("mongodb://localhost:27017/mymondb", function(err, db) {
if(err) throw err;
// Write databse Insert/Update/Query code here..
console.log('mongodb is running!');
db.close(); // 關閉連線
});
這個例子裡,我們載入 MongoDB module,並且使用 MongoClient 物件。
接著,使用 MongoClient.connect() 方法,以取得 MongoDB 資料庫的引用。
其中,URL 的部份,"mongodb://localhost:27017/mymondb"
,指向你之前指定的 MongoDB 資料夾位置 C:\myapp\testdb
。
connect() 方法,會回應一個 database 參考 ,如果所描述的 database (這裡的例子叫做 mymondb) 存在,就連線;無就自動新增。
我們來看看,以上例子,如果有成功連線時的執行結果:
當我們建立了 Node.js 與 MongoDB 連線後,可以使用 connect() 裡的回呼函式其 DB 參數,開始做一些新增Insert(Create)、更新Update、查詢Query(Retrieve/Read)、刪除Delete 資料的動作。
現在,我們來為我們的資料庫新增一些資料。
let MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/mymondb", function(err, db) {
if(err) throw err;
//Write databse Insert/Update/Query code here..
db.collection('Persons',function(err, collection) {
collection.insert({ id:1, firstName:'Steve', lastName:'Jobs' });
collection.insert({ id:2, firstName:'Bill', lastName:'Gates' });
collection.insert({ id:3, firstName:'James', lastName:'Bond' });
collection.count(function(err, count) {
if(err) throw err;
console.log('Total Rows:' + count);
});
});
db.close(); // 關閉連線
});
在這個例子中,我們用 db.collection 方法去新增並且獲取 collections 的一些資訊,如總筆數。
別忘了,在介紹 MongoDB 與關聯式資料庫的關係時,我們知道 collection 其實就是 table
。
而這個例子裡,我們在 mymondb 資料庫 建立了一個 Persons - collection(資料表),並且,為這 Persons 資料表新增了 3 筆資料,我們在這裡叫 documents (列)。
結果如圖:
我們也可以使用 Mongo Shell,查詢:
做完了新增,如果我們想要更新其中 id == 1 的資料。
let MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/mymondb", function(err, db) {
db.collection('Persons',function(err, collection) {
// collection.update
// 第一個參數是要更新的條件
// 第二個參數 $set:更新的欄位及內容
// 第三個參數 writeConcern
// 第四個參數執行 update 後的 callback 函式
collection.update(
{ id: 1 },
{ $set: { firstName: 'James', lastName: 'Gosling'} },
{ w: 1 },
function(err, result) {
if(err) throw err;
console.log('Document Updated Successfully');
}
);
});
db.close(); // 關閉連線
});
我們在終端機執行 node,並且在 Mongo Shell 可以看到更新前與更新後的資料,如圖:
這個網站有詳細說明,可以去參考看看,我們這裡使用,常用的 {w:1}
即可,不用也沒差!
現在,我們想要刪除 id == 2 的 Document(Row)。
let MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/mymondb",function(err, db) {
db.collection('Persons', function(err, collection) {
collection.remove(
{ id: 2 },
{ w: 1 },
function(err, result) {
if(err) throw err;
console.log('Document Removed Successfully!');
}
);
});
db.close(); // 關閉連線
});
我們在終端機執行 node,並且在 Mongo Shell 可以看到刪除前與刪除後的資料,如圖:
維持 Persons 新增後的狀態!即原本的3筆!現在,我們想要找 firstName == "Bill"。
let MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/mymondb", function(err, db) {
db.collection("Persons", function(err, collection) {
collection.find({ firstName: "Bill" }).toArray(function(err, items) {
if(err) throw err;
console.log(items);
console.log("We found " + items.length + " results!");
});
});
db.close(); // 關閉連線
});
我們在終端機執行 node,可以看到被擷取出來的結果,如圖:
!!重要!!
關於更多 Collection 的操作,可以參考:Collection Methods,特別在使用查詢 find,有不同於以往 SQL 的使用語法。
作者:Wayne (偉恩)
連結:https://wayne-blog.com/
來源:Wayne's blog | 偉恩的部落格 | 技術博客