【Spring Boot】第7.1課-MongoDB 介紹與準備資料庫環境 #2024 年更新


https://unsplash.com/photos/LmyPLbbUWhA

後端程式需要透過資料庫來儲存與查詢資料。在先前的文章,範例程式都是以 Java 的 Map 資料結構來暫存,一旦重新啟動程式,資料便消失了。

在第 7 課系列中,本文首先會介紹 MongoDB 這款資料庫。接著運行服務,並在 Spring Boot 專案中確認可以連線。最後簡單介紹 MongoDB 的語法。

一、MongoDB 介紹

(一)什麼是 NoSQL

提到資料庫,讀者可能會先聯想到如 MySQL、SQL Server 與 Oracle 等常見的關聯式資料庫。這種資料庫,會透過資料表設計來規定內容。也透過約束(constraint)來要求不同表的資料必須能保持關聯。

與之相對的是「NoSQL」(Not Only SQL),使用上不需要去設計資料表或約束關係。以下列出幾種常見的 NoSQL,它們都有各自適用的場景。

  • MongoDB:使用 JSON 格式儲存資料,故內容可直接與程式物件對應。適合希望能隨著需求,靈活調整資料欄位的系統。此外也易於進行「反正規化」,若設計得當,有助於讓應用程式更快地得到查詢結果(系列文章)。
  • Redis:以一組「鍵值對」(key-value pair)的形式,來儲存每一筆資料。由於運行時,資料會載入到記憶體中,因此適合作為快取的用途(系列文章)。
  • Elasticsearch:同樣使用 JSON 格式儲存資料。本身是一種「全文檢索引擎」,除了一般查詢,更大的特色是提供關鍵字查詢與相關度評分的功能。因此適合用來開發站內搜尋與推薦系統(系列文章)。

(二)集合與文件

在關聯式資料庫中,會使用「資料表」(table)來儲存資料,而一筆資料稱為「資料列」(row)。

在 MongoDB 中,則使用其他名詞來對照這兩個概念。「集合」(collection)對應到資料表,而「文件」(document)對應到資料列。換句話說,文件會以 JSON 格式記錄資料內容,而集合會儲存許多文件。

MongoDB 會為每一筆文件產生叫做「_id」的欄位,它相當於資料的主鍵,不會有重複值。其資料型態預設為特有的「Object Id」,而值由 24 個 0~9 與 a~f 字元組成。值的產生與當下時間有關,因此有遞增的現象。

在使用 Spring Boot 串接 MongoDB 時,文件還會被自動加入叫做「_class」的欄位。它的值會是 Java 類別的 package 路徑,這是為了讓程式在將文件內容轉換成 Java 物件時,能夠知道目標類別。

二、準備 MongoDB 環境

(一)Docker 容器

讀者可在命令列(command line)環境下,透過 Docker 指令啟動 MongoDB 的服務。

docker run -d --name "MongoDB_4.4.29" -p 27017:27017 mongo:4.4.29

以上取用的 MongoDB 版本為 4.4.29。容器取名為「MongoDB_4.4.29」,運行在 27017 的 port 號上。

其他版本可參考 Docker Hub。關於 Docker 的操作,本文將不詳細介紹。

(二)圖形化介面工具

為了直接查詢資料庫中的資料,或者進行寫入,讀者可安裝圖形化介面(GUI)工具。本文選擇「NoSQL Booster」。

開啟 GUI 後,點擊左上方的「Connect」按鈕,會出現管理資料庫連線設定的視窗。若讀者想存取不同伺服器上的資料庫,就能在這裡建立多個需要的連線(connection)。

nosqlbooster-connections

按下「Create」按鈕,可填寫設定並建立一個連線。

在上圖中,「Server」欄位填寫的是資料庫的位址與 port 號。而「Name」欄位是為這個連線命名,方便我們在 GUI 辨識。

最後按下「Save & Connect」按鈕,就能連線到資料庫。

(三)建立資料庫

按下 GUI 上方的「SQL」按鈕,可開啟查詢視窗。下圖撰寫了兩句語法。

nosqlbooster-use-query-to-create-database-collection

使用 use,可切換到指定的資料庫,即便不存在也可切換。此處選擇叫做「school」的資料庫。

使用 db.createCollection,可在資料庫中建立集合(collection),此處建立叫做「student」的集合。

按下「Run」按鈕,就會執行視窗中的全部指令。由於 school 這個資料庫中開始有內容了,此時它才會被建立出來。

以上這些操作,其實不透過指令,也能藉由 GUI 也能完成,讀者可自行探索。


三、準備程式專案

本節讓我們在 Spring Boot 專案中串接資料庫。請在 pom.xml 檔案添加 MongoDB 的依賴。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

接著在專案的「src\main\resources」路徑下,找到一個叫做「application.properties」的檔案,並在裡頭添加連線字串。以下是在本地連線到叫做「school」的資料庫。

spring.data.mongodb.uri=mongodb://localhost:27017/school

若讀者未來要在 Docker 容器中運行 Spring Boot,可能需將網域從「localhost」改為「host.docker.internal」,如下:

spring.data.mongodb.uri=mongodb://host.docker.internal:27017/school

最後請啟動 Spring Boot。若 console 沒有出現 exception 訊息,代表有成功連線到 MongoDB 的服務。若連線不到,可能會看到如下的訊息。

com.mongodb.MongoSocketOpenException: Exception opening socket
...
Caused by: java.net.ConnectException: Connection refused: no further information
...

這份叫做 application.properties 的檔案,在「【Spring Boot】第13課-在 application.properties 配置檔提供參數」文章會專門介紹。讀者只要知道 library 會從中讀取指定名稱的參數做為連線字串即可。


四、基本語法介紹

為了讓讀者在下一篇練習時,可以透過查詢,直接在 GUI 上確認當前資料庫中的資料,本節將介紹一些語法。在 MongoDB 撰寫大部份指令時,使用的語言為 Javascript。

以下是插入多筆資料到叫做「student」的集合。其中「_id」欄位的值由資料庫自動產生。

db.student.insertMany(
    [
        {
            "name": "Vincent",
            "majority": "資訊管理",
            "contact": {
                "email": "vincent@school.com",
                "phone": "0911111111"
            }
        },
        {
            "name": "Dora",
            "majority": "財務金融",
            "contact": {
                "email": "dora@school.com",
                "phone": "0922222222"
            }
        }
    ]
);

以下是查詢集合中的所有資料。在大括號 { } 中會寫上查詢條件,此處為無條件。

db.student.find({});

以下是查詢「_id」欄位值為某個 Object Id 的資料。

db.student.find(
    {
        "_id": ObjectId("6640d57d4825f6a549d85c08")
    }
);

以下是查詢「majority」欄位值為給定陣列元素其中之一的資料。

db.student.find(
    {
        "majority": {
            "$in": ["資訊管理", "會計"]
        }
    }
);

以下是查詢「contact」物件欄位中的「email」欄位,是某個值的資料。

db.student.find(
    {
        "contact.email": "vincent@school.com"
    }
);

以下是刪除集合中的所有資料。

db.student.deleteMany({});

更多語法,可參考筆者寫的 MongoDB 文章系列:【MongoDB】如何撰寫查詢語法

本文的完成專案:
https://github.com/ntub46010/SpringBootTutorial/tree/Ch7-1

上一篇:【Spring Boot】第6課-元件的控制反轉、依賴注入與多型呼叫

下一篇:【Spring Boot】第7.2課-使用 Spring Data 存取 MongoDB 資料庫,進行基本 CRUD 操作

留言

張貼留言