大家好! 🤗 如果你是剛開始接觸資料庫的開發人員,或者你已經掌握了基礎知識,但正在尋找複習或更深入的理解,我希望這篇文章能對你有所幫助。
學習新事物時,我喜歡深入挖掘,理解背後的邏輯,確保完全理解。因此,本文從NoSQL基礎知識講起,一直到內部資料儲存機制,重點在於闡述資料庫背後的原理。祝您閱讀愉快! 🥰
本文將探討以下內容:
<a href="">我們的起點:SQL 世界</a>
<a href="">NoSQL 的故事:不只是 SQL</a>
<a href="">從本地儲存到資料庫</a>
<a href="">基本CRUD操作:建立、讀取、更新、刪除</a>
當我們使用MySQL或PostgreSQL等關係型資料庫時,資料會整齊地排列在結構完美的表格中。我們必須確保每一行都遵循預先設定的嚴格列結構。如果需要更改這種結構,我們必須立即停止開發,處理複雜的變更,並祈禱所有現有資料仍然能夠相容。
我們確實從中獲得了一致性和邏輯性,但是隨著我們的應用程式不斷擴展,這種僵化成為了快速發展的真正瓶頸。
提到NoSQL資料庫,你可能聽說過它意味著「無 SQL」 ,但讓我們澄清一下:它並非與SQL全面對抗!正確且現代的解釋是:不只是 SQL !
我們意識到SQL在某些特定任務(例如需要嚴格關係和一致性的任務)中表現出色,但如今的現代應用程式(例如社交網路、遊戲和網站)更注重速度和靈活性。 NoSQL 是一種NoSQL ,一種替代方案,使我們能夠根據具體任務選擇合適的工具。我們並沒有放棄SQL ,只是為我們的工具包增添了更強大的工具。
在眾多類型的NoSQL資料庫中,MongoDB 屬於以文件為導向的類別。
想像一下,資料不再儲存在單獨的行和列中。相反,您可以將完整的記錄(例如,包含所有地址、訂單和偏好的使用者個人資料)儲存在一個名為「文件」的單一套件中。
→ 文件是基本建構塊。它看起來與JSON (JavaScript 物件表示法)物件完全相同,但嚴格來說,MongoDB 使用的是BSON (二進位JSON )。為什麼是 BSON?因為它是一種速度更快的二進位格式,並且還包含簡單JSON沒有的資料類型(例如日期/時間值)。
→ 所有這些文件(注意,它們不必完全相同)都被分組到一個集合中,集合是一種取代舊表的資料夾。為了便於理解,我們可以把文件想像成儲存在localStorage中的值,但它們的功能遠比localStorage中的簡單字串值強大得多❗
→ 文件是 MongoDB 中最小也是最重要的資料單元,它包含了完整的訊息,並提供了極大的靈活性,允許:
→ 儲存嵌套物件,
→ 儲存列表,
→ 直接儲存複雜資料類型(例如日期/時間)。
這裡有一份Document :
{ // unique ID
"_id": ObjectId("61a5c6f0e8f0b7c4d5a9b8c7"),
// complex data type: Date/Time
"order_date": ISODate("2025-11-18T10:00:00Z"),
"status": "Shipped",
// nested object
"shipping_address": {
"street": "10 Example Blvd",
"city": "London",
"zip_code": "SW1A 0AA"
},
// list (Array)
"items": [
{
"product_name": "Laptop Pro",
"quantity": 1,
"price": 1200.00
},
{
"product_name": "Mouse Wireless",
"quantity": 2,
"price": 25.50
}
]
}
→ 如果文件相當於單一記錄(例如儲存在localStorage中的複雜值或SQL表中的一行),那麼 MongoDB 中的集合就是將所有這些記錄保存在一起的資料夾。
→ Collection在概念上等同於關係型( SQL )資料庫中的表。與SQL表中所有行必須遵循相同結構(相同列)不同,MongoDB Collection中的Documents可以具有不同的結構(動態模式)❗
→ 舉個簡單的例子,在 MongoDB 中,我們有一個名為school資料庫。這個資料庫包含兩個Collections :students 和 teachers。
,
→ 1. students資料庫包含兩份文件:
{
first_name: "Alice",
last_name: "Smith",
age: 16,
grade: 10,
enrollment_date: new Date("2024-09-01T00:00:00Z"),
courses: ["Math", "Physics", "English"] // Array
},
{
first_name: "Bob",
last_name: "Johnson",
age: 17,
grade: 11,
enrollment_date: new Date("2023-09-01T00:00:00Z"),
contact: { // nested object
phone: "555-1234",
email: "[email protected]"
}
}
Collection包含兩份文件: {
title: "Mr.",
last_name: "Davis",
subject: "Mathematics",
tenure: true,
phone: "555-5678"
class_count: 5
},
{
title: "Ms.",
last_name: "Garcia",
subject: "History",
class_count: 4,
office_hours: { // Nested Object
day: "Wednesday",
time: "2:00 PM - 3:00 PM"
}
}
→ 一個使用者文件可能包含phone號碼字段,而下一個使用者文件可能不包含。這種動態模式是開發人員在處理快速變化的資料時選擇 MongoDB 的主要原因。
→ 因此,MongoDB 允許我們像物件(文件)一樣自然地對資料進行建模,並且這些物件在稱為Collections邏輯群組中得到高效管理。
_id→ 每個文件都必須有一個名為_id的唯一欄位。此欄位用作文件的主鍵(就像 SQL 行中的唯一 ID 一樣)。
→ 如果您在插入資料時沒有指定 _id,MongoDB 會自動使用名為ObjectId的特殊資料類型為您產生一個。此 ObjectId 保證唯一,甚至包含時間戳,讓您可以取得文件建立的確切時間。
(假設 MongoDB 伺服器已安裝且 mongosh 已準備就緒,我們現在可以連接到資料庫,看看如何建立集合和文件)…
→ CRUD操作代表了任何持久化資料儲存系統所依賴的四個基本功能。在資料庫(例如 MongoDB,儘管這些術語也普遍適用)的上下文中,這些是我們與Collection中的Documents互動的方法。
insertOne() / insertMany()→ Create操作會將新文件新增至集合。
insertOne(document) : 此方法用於向集合中插入單一新文件。
//this will add a new document in
//teachers collection
db.teachers.insertOne({
title: "Mr.",
last_name: "Jack",
subject: "Geography",
tenure: false,
phone: "555-5566"
class_count: 6
})
insertMany([document1, document2, ...]) :此方法用於透過單一指令將多個文件插入集合中。參數是一個文件陣列(列表)。
//this will add two documents in
//students collection
db.students.insertMany([
{
first_name: "Lea",
last_name: "Casy",
age: 17,
grade: 10
},
{
first_name: "Jessy",
last_name: "Smith",
age: 18,
grade: 10
}
])
find() / findOne()→ Read操作根據篩選條件從集合中檢索文件。
findOne(query) :此方法傳回第一個符合查詢物件中指定篩選條件的文件。如果您知道只需要單一文件(例如,基於唯一 ID),則此方法非常理想。如果未指定查詢(即查詢為空:{}),則傳回集合中找到的第一個文件。
//find the first student with name 'Lea'
db.students.findOne({ first_name: 'Lea' })
find(query) :此方法傳回一個指向所有符合指定篩選條件的文件的遊標。如果查詢物件為空({}),則傳回集合中的所有文件。
//return all of documents from students colection
db.students.find()
//find all students whose age is greater than 16
db.students.find({ age: {$gt: 16 }})
updateOne(filter, update_operation) : 更新與給定過濾器相符的第一個文件。
//finds the document with `first_name 'Jessy'` and
// sets the new grade to false.
db.students.updateOne(
{ first_name: 'Jessy' },
{ $set: { grade: false } }
)
updateMany(filter, update_operation) : 更新所有與給定過濾器相符的文件。
// It selects documents only if the field contact is absent. ($exists: false)
// and add the 'contact' object with default phone and email values.
db.students.updateMany(
// 1. FILTER: Select documents missing the 'contact' field
{ contact: { $exists: false } },
// 2. OPERATION: Use $set to add the new 'contact' object
{
$set: {
"contact.phone": false,
"contact.email": "[email protected]"
}
}
);
→ 基本$set運算子:這是最常用的更新運算子。它指定要修改哪些欄位以及它們的新值。它可以替換現有欄位的值,或在欄位不存在時新增欄位。
基本語法:在更新呼叫中,更新操作部分通常如下所示: {"$set": {"field_name": "new_value", "another_field": 123}} 。
→ 刪除動作會從集合中刪除文件。
deleteOne(filter) :刪除與指定篩選條件相符的第一個文件。
// delete the first student found whose first name is 'Lea'.
db.students.deleteOne({ first_name: "Lea" })
deleteMany(filter) :刪除所有符合指定篩選條件的文件。
// delete all students who are currently in grade 10.
db.students.deleteMany({ grade: 10 });
注意❗如果您使用deleteMany({}) (一個空過濾器),將會刪除集合中的所有文件。使用刪除操作時務必小心謹慎。 🙃
刪除集合: db.students.drop()
刪除資料庫:先選擇use school資料庫,然後使用db.dropDatabase() ` 刪除它。
雖然我還沒有深入研究具體使用的工具,但我寫第一篇文章的目標是對 MongoDB 的基礎知識做一個簡短而紮實的介紹。
MongoDB 的世界浩瀚無垠,值得探索,但我認為這些基本知識至關重要。如果你了解 localStorage 中的資料保存和檢索機制,就可以進行有效的類比,從而更好地理解資料庫中的集合。 🙃
我很快就會發布更詳細的文章,進一步深入探討我們已經學到的概念。希望這篇入門指南對您有幫助!
如果你喜歡這篇文章,學到了新知識,或是想起了自己第一次接觸MongoDB 的經歷,別忘了按讚或留言!非常感謝你的閱讀,也感謝你抽出寶貴時間閱讀這篇文章。期待下次與你交流!祝你程式愉快! 🥰🤗