如何使用 Node.js 和 MongoDB 進(jìn)行 CRUD?
譯文【51CTO.com快譯】MongoDB是最早的NoSQL數(shù)據(jù)存儲(chǔ)之一,也是目前流行的NoSQL數(shù)據(jù)存儲(chǔ)。Node.js的JavaScript運(yùn)行時(shí)繼續(xù)在后端開(kāi)發(fā)中占據(jù)主導(dǎo)地位。它們共同構(gòu)成了一個(gè)高度靈活和動(dòng)態(tài)的技術(shù)堆棧。
Node.js和MongoDB允許快速實(shí)現(xiàn)基本的應(yīng)用程序功能,如CRUD(創(chuàng)建、讀取、更新和刪除)操作。在本文中,我們將使用最新的 Node.js MongoDB 驅(qū)動(dòng)程序(版本 3.6+)來(lái)了解 CRUD 基礎(chǔ)知識(shí)。
Node.js 和 MongoDB 設(shè)置
先在系統(tǒng)上安裝Node.js和MongoDB,以及一個(gè)包含`curl`可用命令的命令行。(如果你使用的是 2018 年以后的 Linux、MacOS 或 Windows 10 版本,則很可能使用[curl](https://curl.se/)。)
下載系統(tǒng)適用的MongoDB后,可以將其安裝為服務(wù)或?qū)⑵渥鳛榭蓤?zhí)行文件運(yùn)行。無(wú)論哪種方式,請(qǐng)通過(guò)打開(kāi)命令行并運(yùn)行`mongo`命令來(lái)確保 MongoDB 正在運(yùn)行。(如果沒(méi)有作為服務(wù)安裝,可能需要將該命令添加到路徑中。)這使你可以訪問(wèn)系統(tǒng)上運(yùn)行的 MongoDB 實(shí)例。
接下來(lái),確保安裝了 Node.js 和 npm。在命令行中,鍵入`node -v`。如果安裝了 Node.js,將獲得版本號(hào)。如果沒(méi)有,則需要下載Node.js并安裝到機(jī)器上。
Curl允許從命令行執(zhí)行簡(jiǎn)單的HTTP請(qǐng)求。例如,運(yùn)行`curl www.google.com`將收到來(lái)自 Google 主頁(yè)的標(biāo)記。
創(chuàng)建一個(gè) Node.js 項(xiàng)目
在文件夾中創(chuàng)建一個(gè)npm init類(lèi)型的新項(xiàng)目。項(xiàng)目名稱可以使用node-mongo-intro。當(dāng)然,你也可以接受其他缺省值。
添加所需的依賴項(xiàng)。在剛創(chuàng)建的項(xiàng)目目錄中,鍵入`npm install mongodb polka --save`. 這將安裝 MongoDB 的 Node.js 驅(qū)動(dòng)程序(允許項(xiàng)目訪問(wèn) MongoDB)和用于處理 HTTP 請(qǐng)求的Polka HTTP 服務(wù)器。
編輯 package.json 文件以包含啟動(dòng)腳本,如Listing 1 所示。
Listing 1. A start script
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/index" // <-- add this line
},
接著創(chuàng)建一個(gè) /node-mongo-intro/src/index.js 文件,并將Listing 2 的內(nèi)容放入其中。
Listing 2. HTTP test in index.js
const polka = require('polka');
polka()
.get('/create', (req, res) => {
res.end(`works`);
})
.listen(3000, err => {
if (err) throw err;
console.log(`> Running on localhost:3000`);
});
現(xiàn)在用`npm run start`啟動(dòng)服務(wù)器。服務(wù)器將在端口3000上偵聽(tīng)。你可以使用curl http://localhost:3000/create進(jìn)行測(cè)試。測(cè)試后應(yīng)該會(huì)看到“works”的響應(yīng)(以及一些curl請(qǐng)求信息)。
在 MongoDB 中插入一條記錄
現(xiàn)在我們將執(zhí)行一個(gè)簡(jiǎn)單的插入。這是 CRUD 中的 “C”。將`index.js`文件更新為如Listing 3 所示。
Listing 3. A simple insert
const polka = require('polka');
const { MongoClient } = require("mongodb");
polka()
.get('/create', (req, res) => {
const client = new MongoClient("mongodb://localhost:27017");
async function run() {
try {
await client.connect();
const database = client.db("intro");
const collection = database.collection("quotes");
const result = await collection.insertOne({"quote":"Life is what happens to you while you're busy making other plans."});
res.end(JSON.stringify(result));
} catch (e) {
console.log("Error: " + e);
} finally {
await client.close();
}
}
run().catch(console.dir);
})
.listen(3000, err => {
if (err) throw err;
console.log(`> Running on localhost:3000`);
});
Listing 3 中的代碼打開(kāi)到本地系統(tǒng)上 MongoDB 實(shí)例的連接,然后指定一個(gè)數(shù)據(jù)庫(kù) ( `"intro"`) 和集合 ( `"quotes"`)。集合類(lèi)似于關(guān)系數(shù)據(jù)庫(kù)中的表。
接下來(lái),代碼插入一個(gè)文檔(類(lèi)似于 SQL 記錄)并在一個(gè)HTTP響應(yīng)中發(fā)送結(jié)果。
運(yùn)行插入
首先,按 Ctrl-C 停止并重新啟動(dòng)節(jié)點(diǎn)服務(wù)器。然后在命令行運(yùn)行這個(gè)命令:
npm run startcurl http : //localhost:3000/create
驗(yàn)證插入
如果你掌握 SQL 技術(shù),你會(huì)注意到的一件事是,我們?cè)谶M(jìn)行這項(xiàng)工作之前沒(méi)有創(chuàng)建表和模式。我們甚至沒(méi)有創(chuàng)建我們使用的數(shù)據(jù)庫(kù)。因?yàn)?MongoDB 為我們完成了這些所需的工作,它可以接受任何類(lèi)型的結(jié)構(gòu)化鍵值文檔到集合中。
使用mongo打開(kāi)mongo shell,并輸入命令use intro。這將切換到自動(dòng)創(chuàng)建的intro數(shù)據(jù)庫(kù)?,F(xiàn)在輸入db.quotes.find()命令,將看到該記錄被插入。注意MongoDB會(huì)在“_id”字段上自動(dòng)生成一個(gè)唯一的ID。你可以通過(guò)在文檔上自己指定一個(gè)來(lái)覆蓋它。
在MongoDB中檢索文檔
現(xiàn)在讓我們把文件拿出來(lái)。添加如 Listing 4所示的.get()映射。這是CRUD中的“R”。
Listing 4. Retrieve a document
.get('/retrieve', (req, res) => {
const client = new MongoClient("mongodb://localhost:27017");
async function run() {
try {
await client.connect();
const database = client.db("intro");
const collection = database.collection("quotes");
const cursor = collection.find({}, {});
let items = [];
await cursor.forEach(function(doc){
items.push(doc);
});
res.end(JSON.stringify(items));
} catch (error){
console.warn("ERROR: " + error);
if (errCallback) errCallback(error);
} finally {
await client.close();
}
}
run().catch(console.dir);
})
Listing 4 以與Listing 3 相同的方式連接,然后發(fā)出一個(gè)`find`命令,并帶有一個(gè)空查詢。這意味著它匹配所有文檔。接下來(lái),它接收響應(yīng)并將其編組到一個(gè)數(shù)組中以發(fā)送回客戶端。
注意,游標(biāo)操作和集合是異步的。清單3中的collection.insertOne也是如此。我們使用await關(guān)鍵字來(lái)處理這些,而不使用嵌套的回調(diào)。
使用curl http://localhost:3000/retrieve測(cè)試新端點(diǎn)(在停止并再次啟動(dòng)服務(wù)器之后),將看到返回的集合。
MongoDB中更新文檔
現(xiàn)在是CRUD中的“U”。Listing 5處理了這一點(diǎn)。
Listing 5. Updating a document
.get('/update', (req, res) => {
const client = new MongoClient("mongodb://localhost:27017");
async function run() {
try {
await client.connect();
const database = client.db("intro");
const collection = database.collection("quotes");
const updateDoc = {
$set: {
author:
"John Lennon",
},
};
const result = await collection.updateOne({}, updateDoc, {}); // <-- empty filter matches all docs
res.end("Updated: " + result.modifiedCount);
} catch (e) {
errCallback(e);
} finally {
await client.close();
}
}
run().catch(console.dir);
})
Listing 5 再次連接到數(shù)據(jù)庫(kù),然后創(chuàng)建一個(gè)更新文檔。本文檔通過(guò)指定一個(gè)`$set`包含要更改的字段和值的對(duì)象的字段來(lái)告訴 MongoDB 要更改什么。在我們的例子中,我們將該`author`字段設(shè)置為`"John Lennon"`,即相關(guān)引用的引用者。
接下來(lái),Listing 5 使用該`updateOne()`函數(shù)來(lái)執(zhí)行更新文檔。最后一個(gè)空對(duì)象參數(shù)是過(guò)濾器。在這種情況下,我們希望匹配所有文檔,因此我們將其留空。
最后,我們發(fā)回我們更新的文檔數(shù)量(一個(gè))。
MongoDB中刪除文檔
CRUD的最后一個(gè)字母是“D”,表示刪除。
刪除操作的映射如Listing 6所示。
Listing 6. Deleting a document
.get('/delete', (req, res) => {
const client = new MongoClient("mongodb://localhost:27017");
async function run() {
try {
await client.connect();
const database = client.db("intro");
const collection = database.collection("quotes");
const query = { };
const result = await collection.deleteOne(query);
if (result.deletedCount === 1) {
res.end("Successfully deleted one document.");
} else {
res.end("Deleted 0 documents.");
}
} finally {
await client.close();
}
}
這里我們?cè)俅问褂每詹樵儊?lái)匹配`"quotes"`集合中的所有文檔。async`collection.deleteOne()`函數(shù)返回一個(gè)結(jié)果,告訴我們有多少文檔受到影響。
重新啟動(dòng)服務(wù)器 (Ctrl-C) 并發(fā)出新的 curl 命令:
curl http://localhost:3000/delete
您可以使用curl http://localhost:3000/retrieve來(lái)驗(yàn)證文檔是否已被刪除。
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】