JavaScript >> Javascript 文檔 >  >> Node.js

如何在 Node.js 中使用 MongoDB

如何使用 Node.js 將 Node.js 應用程序連接到現有的 MongoDB 數據庫。

開始使用

因為我們為本教程編寫的代碼是“獨立的”(意味著它不是更大的應用程序或項目的一部分),所以我們將從頭開始創建一個 Node.js 項目。如果您的計算機上尚未安裝 Node.js,請先閱讀本教程,然後再返回此處。

在計算機上安裝 Node.js 後,從計算機上的項目文件夾(例如,~/projects ),為我們的工作創建一個新文件夾:

終端

mkdir mongodb-tutorial

接下來,我們要安裝兩個依賴,mongodbexpress

終端

npm i mongodb express

第一個將讓我們訪問 MongoDB 的 Node.js 驅動程序(我們將在代碼中使用它來連接到數據庫),第二個 Express 將用於啟動演示服務器。

最後一步:在 package.json 為您創建的文件,請確保添加字段 "type": "module" 作為財產。這將啟用 ESModules 支持並允許我們使用 import 如下代碼所示。

有了這些,我們就可以開始了。

安裝和啟動 MongoDB

在我們深入研究代碼之前,您必須在計算機上安裝並訪問 MongoDB,這一點很重要。如果你 已經安裝了 MongoDB,請在此處按照您的操作系統的“社區版”說明進行操作。

注意 :對於本教程,您只需要確保 MongoDB 已安裝 .您無需按照將 MongoDB 作為後台服務啟動的說明進行操作。如果您了解這意味著什麼,我們非常歡迎您,但我們接下來將介紹另一種啟動服務器的方式。

啟動 MongoDB 服務器

在我們啟動 MongoDB 服務器之前,我們需要一個可訪問的目錄,MongoDB 可以在其中存儲它生成的數據。從我們剛剛在“入門”下創建的項目的根目錄中,我們要創建一個目錄 data 在其中,我們要創建另一個目錄 db .完成後,您的目錄結構應如下所示:

/mongodb-tutorial
-- /data
---- /db

一旦你有了這個,在終端窗口中,cd 進入項目文件夾的根目錄(mongodb-tutorial ) 並運行以下命令:

終端

mongod --dbpath ./data/db

運行此程序後,您應該會看到一些來自 MongoDB 的日誌記錄,該日誌記錄將在幾秒鐘後停止,表示服務器已啟動並正在運行。 注意 :這將在其默認端口 27017 上啟動 MongoDB .當我們在應用程序中連接 MongoDB 連接時,知道接下來會派上用場。

在 Node.js 中連接 MongoDB 適配器

為了將 MongoDB 集成到我們的應用程序中,我們需要做的第一件事——也是最重要的事情——是建立一個連接 使用他們的官方 Node.js 包(稱為“驅動程序”,該術語通常指用於通過代碼連接到數據庫的包或庫)到 MongoDB。

/connectToMongoDB.js

import { MongoClient } from "mongodb";

const connectToMongoDB = async (uri = '', options = {}) => {
  if (!process.mongodb) {
    const mongodb = await MongoClient.connect(uri, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      ssl: process.env.NODE_ENV === "production",
      ...options,
    });

    const db = mongodb.db('example');
    process.mongodb = db;

    return {
      db,
      Collection: db.collection.bind(db),
      connection: mongodb,
    };
  }

  return null;
};

export default await connectToMongoDB('mongodb://localhost:27017', {});

從我們文件的頂部開始,我們要做的第一件事是導入名為 export MongoClient 來自 mongodb 我們之前通過 NPM 安裝的包。 “命名”導出部分由包裹變量名稱的大括號表示,因為沒有大括號表示“默認”導出。

接下來,我們要定義一個函數,負責建立與數據庫的連接。在這裡,我們定義了一個箭頭函數 connectToMongoDB() 這需要兩個參數:urioptions .

這裡,uri 指的是 MongoDB 連接字符串。這是一個特殊的 URI,MongoDB 可以識別並解釋 MongoDB 驅動程序在哪裡可以找到正在運行的 MongoDB 數據庫以連接。對於 options ,這些是我們想要傳遞給驅動程序的任何特殊配置選項(例如,覆蓋默認值或教程中未在此處設置的選項)。

在函數內部,首先,我們確保我們沒有現有的 process.mongodb 價值。這是一個約定我們是 本教程的介紹。正如我們將看到的,我們的目標是讓我們的 MongoDB 數據庫可以在 process 對像上訪問,這樣,如果我們願意,我們可以在我們的應用程序中全局訪問我們的 MongoDB 連接。這樣做的好處是我們可以在整個應用程序中“重用”相同的連接,從而減少 MongoDB 服務器的整體壓力。

如果我們 已將值設置為 process.mongodb ,接下來,我們要告訴驅動連接到傳遞的uri 以及一些默認選項。為此,我們調用 MongoClient.connect() 傳遞 uri (同一個傳遞給我們的 connectToMongoDB() 函數作為第一個參數)我們要連接的第一個參數,後面是一個包含該連接選項的對像作為第二個參數。

對於我們作為第二個參數傳遞的選項對象,我們傳遞了三個默認值:

  1. useNewUrlParser 它告訴驅動程序尊重較新的 mongodb+srv:// 連接 URL 的樣式。
  2. useUnifiedTopology 它告訴驅動程序使用新的、更高效的“拓撲”(MongoDB 對數據庫核心部分的內部名稱),它將數據庫的所有重要部分組合在一起。
  3. ssl 它告訴 MongoDB 它是否應該只接受通過安全 SSL 連接的連接。在這裡,設置為 true 僅當 process.env.NODE_ENV 的值 是 "production" .

最後,在這些默認值下,我們使用 JavaScript 擴展 ... 操作員說“採取任何傳遞的選項並將它們傳播(或“複製”)到我們在這里傳遞的對像上。換句話說,在 options 上定義的任何屬性 我們作為第二個參數傳遞給 connectToMongoDB 的對象 將被複製到我們傳遞給 MongoClient.connect() 的選項對像上 .此外,如果您想以不同方式配置上面列出的三個默認選項之一,如果您指定一個值(例如,如果您設置 useUnifiedTopology: false 在您的 options 上 對象,這將覆蓋默認的 true 版本)。

接下來,我們的連接(大概)在 mongodb 中可訪問 我們分配的變量 await MongoClient.connect() 調用,接下來,我們創建另一個變量 db 並將其分配給 mongodb.db('example') example 是我們要在 MongoDB 服務器上連接的任意數據庫名稱(應替換為您自己的數據庫名稱)。

我們在這裡調用它是因為它讓我們可以快速訪問我們正在連接的 MongoDB 數據庫,從而避免我們必須寫出 .db('<database>') 參與我們要運行的每個查詢。接下來,在此之後,我們分配 db process.mongodb 的值 (記得我們之前暗示過)。現在,這使我們可以在整個應用程序中全局訪問 MongoDB 數據庫。

更進一步:從我們的函數中,我們希望返回一個對象,該對象使我們能夠以各種方式訪問我們的 MongoDB 連接。這為我們的代碼提供了靈活性,因此我們不會受限於對數據庫的訪問受限。

在那個對像上,我們定義了三個屬性:

  1. db 這是 db 我們剛剛創建並在上面解釋過的變量。
  2. Collection 這是一種“hack”,它允許我們快速為數據庫中的特定集合創建句柄。
  3. connection 這是我們用 MongoClient.connect() 建立的原始連接 .

最後,在我們的 connectToMongoDB() 底部 函數,我們返回 null 如果 process.mongodb 已經設置好了。

在我們繼續之前,此文件中還有一件事。您會注意到,在文件的最底部,我們添加了對 connectToMongoDB() 的調用的默認導出 功能。這是故意的。這使我們可以在應用程序中導入此文件的任何位置自動建立與 MongoDB 的連接。如果我們看一下,我們將 MongoDB 數據庫的 URI 硬編碼為傳遞給函數 mongodb://localhost:27017 的第一個參數 .

這將被傳遞給 connectToMongoDB() 作為 uri 參數,並最終成為驅動程序嘗試連接的數據庫。因為我們使用了 async connectToMongoDB()前面的關鍵字 , 調用時,它本身會返回一個 JavaScript Promise 對象,因此,在文件底部的調用之前,我們使用 await 再次關鍵字說“在導出值之前等待連接建立。”

有了這個,我們的連接就完成了。接下來,我們將看一些在我們的應用中使用它的示例。

創建集合和測試數據

首先,為了演示我們的連接,我們需要一些測試數據才能工作。這是一個了解自定義 Collection 的絕佳機會 我們從 /connectToMongoDB.js 導出的函數 文件有效。

/books.js

import MongoDB from './connectToMongoDB.js';

const Books = MongoDB.Collection('books');

if (await Books.countDocuments() < 3) {
  await Books.bulkWrite([
    {
      insertOne: {
        document: {
          title: 'The Culture We Deserve',
          author: 'Jacques Barzun',
          year: '1989',
        },
      },
    },
    {
      insertOne: {
        document: {
          title: 'The Fabric of Reality',
          author: 'David Deutsch',
          year: '1998',
        },
      },
    },
    {
      insertOne: {
        document: {
          title: 'The Bitcoin Standard',
          author: 'Saifedean Ammous',
          year: '2018',
        },
      },
    }
  ])
}

export default Books;

首先,在我們文件的頂部,我們從 /connectToMongoDB.js 導入了默認導出 我們上面寫的文件(調用await connectToMongoDB()的結果 )。在 MongoDB 這裡的變量,我們希望有我們從 connectToMongoDB() 返回的對象 功能。

請記住,在該對像上,我們添加了一個特殊屬性 Collection 這為我們提供了一種使用更少代碼連接到 MongoDB 集合的簡單方法。在這裡,為了創建一個新集合的句柄 books ,我們調用 MongoDB.collection('books') .這做了兩件事:

  1. 創建 books MongoDB 中的集合(如果它尚不存在)。
  2. 返回集合句柄以在我們代碼的其他地方使用。

“句柄”是指對集合的引用。我們可以看到這個句柄在下面我們嘗試使用一些測試數據為數據庫播種。在這裡,我們說“如果 Books.countDocuments() 返回小於三的數字,將以下文檔插入該集合。”

沒有這個,我們就不得不寫...

await process.mongodb.collection('books').countDocuments();

or

MongoDB.db.collection('books').countDocuments();

感謝我們的 Collection 更加簡潔 功能。

雖然它與我們這裡的工作沒有太大關係,但在 if 內部 聲明,假設我們 現有三本書,我們調用 .bulkWrite() MongoDB作為驅動程序的一部分提供的方法,為我們的測試數據插入三本書。

重要的部分:在我們文件的底部,我們採用 Books 我們將集合句柄存儲在變量中,並將其作為默認值從我們的文件中導出。當我們從數據庫中讀回一些數據時,這將派上用場。

讀取數據

最後,現在,我們要演示使用我們剛剛使用 MongoDB.Collection() 建立的集合句柄從 MongoDB 讀取數據 .為此,我們將使用單個路由 /books 連接一個簡單的 Express.js 應用程序 我們可以在其中檢索我們收藏中的當前書籍列表。

/index.js

import express from 'express';
import Books from './books.js';

const app = express();

app.get('/books', async (req, res) => {
  res.setHeader('Content-Type', 'application/json');
  res.status(200);
  res.send(JSON.stringify({ books: await Books.find().toArray() }, null, 2));
});

app.listen(3000, () => {
  console.log('App running on localhost:3000');
});

Express 部分的快速概覽:在這裡,我們導入 express 來自 express 我們之前安裝的包,然後通過調用 express() 創建一個新實例 作為函數並將該實例存儲在變量 app 中 .

接下來,在我們文件的底部,我們在端口 3000 上啟動我們的 Express.js 服務器 通過調用 app.listen() 並提供一個回調函數,讓我們在終端上註銷一條消息,讓我們知道服務器正在運行。

這裡我們關心的部分:在中間,我們添加了對 app.get() 的調用 它在我們的應用程序 /books 中定義了一個路由 支持 HTTP GET 要求。對於該路由,我們定義了一個處理函數(注意 async 的用法 在函數前面,表示我們將使用 await 函數內部的某處),旨在以我們的書籍列表進行響應。

為此,我們確保設置 Content-Type res 上的標頭 ponse 對像到 application/json ,然後提供 200 的 HTTP 狀態碼 (意思是oksuccess ) 最後,調用 res.send() ,傳遞一個 JSON.stringify() 調用,我們向其傳遞一個具有 books 屬性的對象 分配給調用 await Books.find().toArray() 的結果 它利用了 Books 我們在上一步中創建的處理程序,用於對我們的圖書集合執行查詢。

而已!如果我們確保我們的 MongoDB 數據庫已啟動並運行,然後使用 node index.js 啟動此服務器 從我們的終端(您將需要一個用於 MongoDB 的終端窗口/選項卡和一個用於此 Express 服務器的終端窗口/選項卡),如果我們訪問 http://localhost:3000/books,我們應該會看到我們的書籍顯示 .

總結

在本教程中,我們學習瞭如何使用官方的 mongodb 連接到 MongoDB 數據庫 包裹。我們學習瞭如何編寫一個包裝函數來幫助我們建立這種連接以及一些方便的方法,以便在我們的代碼中更輕鬆地與 MongoDB 交互。我們還學習瞭如何創建一個新集合併使用一些數據為其播種,以及如何讀取 通過 Express.js 中的路由從集合中返回數據。


Tutorial JavaScript 教程
  1. 🌙 我如何為 Gatsby 網站設置暗模式

  2. 樣式化控制台消息

  3. Rails 中的 React 上下文模式

  4. 在沒有 nodemon 的情況下重新加載 express 服務器

  5. 為大型應用程序簡化 Redux 中異步操作的請求/成功/失敗模型

  6. 回發和回調之間的區別

  7. React/Redux 應用程序與 Azure DevOps:第 9 部分集成測試和端到端測試

  1. JavaScript 顯示錯誤的日期年份

  2. 使用 Promise.all 和 async / await 獲取

  3. 刷新頁面時清除上下文值(來自狀態)

  4. 💜 學習 React Hooks 的合集! 🎣

  5. 客戶端 html markdown 轉換

  6. 讓我們開發一個 QR 碼生成器,第五部分:屏蔽

  7. 編程:人類哲學

  1. 哪些軟件技術將為您帶來最高的報酬?

  2. 另一個 Web 開發 YouTube 頻道

  3. 為什麼我切換到 PNPM?

  4. #2 將 graphql 添加到 express 服務器