【MongoDB】建立資料庫與基本語法介紹


https://flic.kr/p/qakxAH

MongoDB 是一款 NoSQL 資料庫。它與關聯式資料庫最大的不同,是以類似 JSON 格式的方式來儲存資料。使用上也沒有嚴格的 schema 跟 constraint,因此在欄位設計與資料儲存上能夠更有彈性。本文將會建立 MongoDB 資料庫,並示範最基本的 CRUD(新增、查詢、修改與刪除)語法。

一、安裝 MongoDB 與使用圖形化介面工具

關於安裝資料庫的方式,可參考筆者這篇文章的第一節,並留意開啟與關閉 Windows 服務的方式。在安裝過程中,會遇到一個步驟是詢問是否要安裝工具「MongoDB Compass」。此處不需要安裝,因為在這系列文章,筆者會使用另一個圖形化介面工具(GUI Tool),叫做「NoSQLBooster」。

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

按下「Create」按鈕,可以填寫連線設定並建立一個連線。在下圖中,「Server」欄位填寫的是資料庫的位址與埠號。而「Name」欄位是命名我們要在 GUI 看的名稱。若讀者想連線的資料庫有帳密保護,請到「Authentication」頁籤做其他設定。最後按下「Save」按鈕即可儲存,再按下「Connect」就能連線到資料庫。

連線到資料庫後,讓我們開始在上面建立資料庫。在 NoSQLBooster 畫面的左上方,有個「Open Connection」區塊。請在要操作的連線上按右鍵,選擇「Create Database」,輸入資料庫名稱後按下 OK。此例筆者輸入的名稱是「StudentGrade」,是一個儲存學生成績的資料庫。

接著在資料庫上按右鍵,選擇「Create Collection」。在 MongoDB,這裡的 collection(集合)如同關聯式資料庫的 table;而 document(文件)指的則是存放的資料。此例的 collection 名稱為「student」,用來存放學生的 document。


二、新增資料

建立好資料庫和 collection 後,就能開始學習語法了。在左邊的 Open Connection 區塊,對想要操作的連線按右鍵,選擇「Run SQL Query」,可在右邊開啟撰寫語法的視窗。MongoDB 的語法有點像 JavaScript。我們可以用「物件.方法」的模式來撰寫,並用大括號 { } 來宣告物件,用中括號 [ ] 來宣告陣列,再傳入方法中。

這一節會從新增資料的語法開始。首先寫出 db.student,代表要對資料庫的 student 集合進行操作。接著寫下 .insertOne(),呼叫新增一筆資料的方法,我們對該方法傳入一個物件參數。

db.student.insertOne(
    {
        "studentId": "10346000",
        "name": "Vincent",
        "majority": ["資訊管理", "財務金融"]
    }
)

隨後即可按下上方的「Run」按鈕執行,如下圖。

在下方的 console 視窗能看到回傳結果。其中 insertedId 的值是一個「ObjectId」,它是 MongoDB 為 document 自動產生的 id。

若讀者想要一次新增多筆資料,可以使用 insertMany 方法,傳入 document 的陣列。

db.student.insertMany(
    [
        {
            "studentId": "10342000",
            "name": "Dora",
            "majority": ["財務金融"]
        },
        {
            "studentId": "10345000",
            "name": "Winnie",
            "majority": ["企業管理"]
        }
    ]
)

而回傳結果同樣包含已新增文件的 ObjectId。

另外還有一個比較舊版,且已被 deprecated 的 insert 方法,它的參數同時接受物件與陣列。與上述兩者的差別在於回傳的結果,insert 方法只會回傳新增的資料筆數。

三、查詢資料

新增完資料後,讓我們看看儲存的狀況。使用 find 方法可以進行查詢,它接受一個物件參數,代表查詢條件。若沒有條件,則傳入「空物件」就好,以取得 collection 中的所有資料。

db.student.find(
    {}
)

下圖為查詢結果。檢視方式是 Tree,讀者亦可在右上方切換成其他的,如 JSON、Table。

接下來使用單一欄位來查詢。此處查詢 name 欄位為「Vincent」的學生。做法是在查詢條件的物件中添加屬性,key 為欄位名稱,value 為目標的值。

db.student.find(
    {
        "name": "Vincent"
    }
)

再來是針對陣列欄位來查詢。此處查詢 majority 欄位為「財務金融」的學生。比較特別的是,只要陣列元素包含這個值,就算符合條件。以此例來說,會找出兩個 document。

db.student.find(
    {
        "majority": "財務金融"
    }
)

最後示範用 document 的 id 來查詢。要注意的是「_id」的值需給予 ObjectId。

db.student.find(
    {
        "_id": ObjectId("61f8dfcbaa42a213609a6990")
    }
)

本文只介紹簡單的查詢。更多查詢方式,請參考官方文件或筆者的下一篇【MongoDB】如何撰寫查詢語法


四、刪除資料

本節來學習刪除資料的語法。其實與查詢資料類似,都需要傳入查詢條件。我們假設 student 這個 collection 中有以下資料。

(一)deleteOne 方法

使用 deleteOne 方法可刪除查詢到的第一筆資料。以下的語法是刪除 _id 欄位為給定 ObjectId 的一筆資料。

db.student.deleteOne(
    {
        "_id": ObjectId("61fb84671d8a0e494354075d")
    }
)

該方法會回傳一個物件,內含已刪除的資料筆數。

{   
    "acknowledged": true,
    "deletedCount": 1
}

(二)deleteMany 方法

使用 deleteMany 方法可刪除查詢到的所有資料。以下的語法是刪除 grade 欄位的值為 4 的所有資料。該方法也會回傳與 deleteOne 方法相同的物件,以此例來說,deletedCount 的值為 2。

db.student.deleteMany(
    {
        "grade": 4
    }
)

(三)findOneAndDelete 方法

使用 findOneAndDelete 方法可刪除查詢到的第一筆資料,並回傳該筆資料。若未查詢到資料,則回傳 null。以下的語法是刪除 majority 欄位為「財務金融」的資料。

db.student.findOneAndDelete(
    {
        "majority": "財務金融"
    }
)

以此例來說,雖然有兩筆資料符合條件,但仍只會刪除並回傳第一筆資料。以下是在 console 視窗印出的內容。

{
    _id: new ObjectId("61fb84671d8a0e4943540759"),
    name: 'Vincent',
    majority: [ '資訊管理', '財務金融' ],
    grade: 3
}

若再執行一次,才會刪除下一筆。


五、更新資料

本節來學習更新資料的語法,更新與刪除都需要傳入查詢條件。不過讀者可以對欄位指定各式各樣的更新方式。本節我們同樣假設 student 這個 collection,其初始資料與上一節相同。

使用 save 方法,並傳入一個物件,可以覆蓋具有相同 _id 欄位值的 document。適合用於事先將資料查詢出來,單純用程式碼進行修改內容,再存回 collection 的場景。有點像在用 JavaScript 寫預存程序(Stored Procedure)。

以下的範例是查出 collection 中所有資料,將 majority 陣列欄位的每個元素加上「系」字,再儲存。

// 查詢資料
const students = db.student.find({}).toArray()

students.forEach(stu => {
    // 修改資料
    const majority = stu.majority.map(m => m += "系")
    stu.majority = majority
    
    // 儲存
    db.student.save(stu)
})

使用 updateMany 方法,除了傳入查詢條件,讀者還可搭配各種操作符號來實現想要的更新方式。

(一)$set 操作符號

使用 $set 符號可以更新欄位的值。若欄位不存在,則視為新增欄位並給予該值。以下的範例是查出 name 欄位值為「Vincent」的資料,修改其 name 欄位值,並新增 birthday 欄位。

db.student.updateMany(
    {
        "name": "Vincent"
    },
    {
        "$set": {
            "name": "Vincent Zheng",
            "birthday": ISODate("1996-01-01")
        }
    }
)

(二)$unset 操作符號

使用 $unset 符號可以移除指定欄位。以下的範例是移除所有 document 的 birthday 欄位。

db.student.updateMany(
    {},
    {
        "$unset": {
            "birthday": ""
        }
    }
)

關於 birthday 的值給予空字串,MongoDB 的文件提到給予的值不會影響操作。所以隨意給個值即可。

(三)$inc 操作符號

使用 $inc 符號,可以將數值欄位的值增加我們給予的值,也能提供負數或小數點。以下的範例是將所有 document 的 grade 欄位值增加 1。

db.student.updateMany(
    {},
    {
        "$inc": {
            "grade": 1
        }
    }
)

本文只簡單地介紹幾個操作符號。更多操作方式,請參考官方文件或筆者的【MongoDB】使用操作符號來更新資料文章。

下一篇:【MongoDB】如何撰寫查詢語法

留言