MongoDB 作為一種 NoSQL 資料函式庫,以其靈活的檔案模型和豐富的查詢功能而聞名。本文除了介紹基本的 CRUD 操作外,也涵蓋了進階的查詢技巧,例如 $or、$in 等,以及如何使用投影操作來提升查詢效率。此外,文章也探討了 MongoDB 的聚合框架,讓開發者能夠運用其強大的資料處理能力進行資料分析和統計。
MongoDB 資料函式庫操作
更新檔案
在 MongoDB 中,更新檔案是常見的操作。可以使用 updateMany() 方法更新多個檔案,或使用 replaceOne() 方法替換整個檔案。
更新多個欄位
db.people.updateMany({name: 'Tom'}, {$set: {age: 30, salary: 50000}})
這將更新所有名字為 ‘Tom’ 的檔案,將年齡設為 30,並新增一個 salary 欄位,值為 50000。
替換檔案
db.collection.replaceOne({name: 'Tom'}, {name: 'Lakmal', age: 25, address: 'Sri Lanka'})
這將替換名字為 ‘Tom’ 的檔案,新的檔案將包含 name、age 和 address 欄位。注意,用於識別檔案的欄位將被保留在更新的檔案中,未在更新區段中定義的欄位將被移除。
刪除檔案
MongoDB 提供了多種方法來刪除檔案。
刪除多個檔案
db.people.deleteMany({name: 'Tom'})
這將刪除所有名字為 ‘Tom’ 的檔案。
刪除單個檔案
db.people.deleteOne({name: 'Tom'})
這將刪除第一個名字為 ‘Tom’ 的檔案。
查詢檔案
查詢是 MongoDB 中最常用的操作之一。
查詢所有符合條件的檔案
db.people.find({name: 'Tom'})
這將傳回所有名字為 ‘Tom’ 的檔案。
查詢第一個符合條件的檔案
db.people.findOne({name: 'Tom'})
這將傳回第一個名字為 ‘Tom’ 的檔案。
指定傳回欄位
db.people.find({name: 'Tom'}, {_id: 0, age: 1})
這將傳回名字為 ‘Tom’ 的檔案的 age 欄位,並排除 _id 欄位。
更新內嵌檔案
內嵌檔案是指巢狀在其他檔案中的檔案。
使用 $ 運算元更新內嵌檔案
db.people.update({name: "Tom", marks: 50}, {"$set": {"marks.$": 55}})
這將更新名字為 ‘Tom’ 且 marks 陣列中包含 50 的檔案,將 50 更新為 55。
更多更新運算元
MongoDB 提供了多種更新運算元,例如 $push、$pull 和 $pop。
$push 運算元
db.people.update({name: 'Tom'}, {$push: {nicknames: 'Tommy'}})
這將在名字為 ‘Tom’ 的檔案的 nicknames 陣列中新增一個元素 ‘Tommy’。
$pull 運算元
db.people.update({name: 'Tom'}, {$pull: {nicknames: 'Tommy'}})
這將從名字為 ‘Tom’ 的檔案的 nicknames 陣列中移除元素 ‘Tommy’。
更新多個檔案的引數
要更新多個檔案,需要設定 multi 選項為 true。
db.collection.update(
query,
update,
{
upsert: boolean,
multi: boolean,
writeConcern: document
}
)
取得資料函式庫資訊
MongoDB 提供了多種方法來取得資料函式庫資訊。
列出所有集合
show collections
或
db.getCollectionNames()
列出所有資料函式庫
show dbs
或
db.adminCommand('listDatabases')
MongoDB 查詢資料基礎
MongoDB 提供多種查詢方法來檢索資料,包括 find()、findOne() 等,並支援多種條件查詢,如 AND、OR、IN 等。
4.1 使用 find() 查詢資料
find() 方法用於檢索集合中的檔案。
檢索集合中的所有檔案
db.collection.find({});
使用條件檢索檔案(類別似於 MySQL 中的 WHERE)
db.collection.find({key: value});
範例:
db.users.find({email:"sample@email.com"});
使用布林條件查詢(Query Operators)
AND
db.collection.find({
$and: [
{ key: value },
{ key: value }
]
})
OR
db.collection.find({
$or: [
{ key: value },
{ key: value }
]
})
NOT
db.inventory.find({ key: { $not: value } })
更多布林操作和範例可參考相關檔案。
注意事項
find() 會持續搜尋集合,即使已經找到符合的檔案。因此,在大型集合中使用時效率較低。然而,透過仔細設計資料模型和使用索引,可以提高 find() 的效率。
4.2 使用 findOne() 查詢資料
findOne() 的查詢功能與 find() 類別似,但它會在找到第一個符合條件的檔案後停止執行。如果使用空物件作為查詢條件,它會取出第一個檔案並傳回。
db.collection.findOne({});
4.3 對 find() 結果進行限制、跳過、排序和計數
與聚合方法類別似,find() 也支援對結果進行限制、跳過、排序和計數。
範例集合
db.test.insertMany([
{name:"Any", age:"21", status:"busy"},
{name:"Tony", age:"25", status:"busy"},
{name:"Bobby", age:"28", status:"online"},
{name:"Sonny", age:"28", status:"away"},
{name:"Cher", age:"20", status:"online"}
])
列出集合中的所有檔案
db.test.find({})
結果:
{ "_id" : ObjectId("592516d7fbd5b591f53237b0"), "name" : "Any", "age" : "21", "status" : "busy" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b1"), "name" : "Tony", "age" : "25", "status" : "busy" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b2"), "name" : "Bobby", "age" : "28", "status" : "online" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b3"), "name" : "Sonny", "age" : "28", "status" : "away" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b4"), "name" : "Cher", "age" : "20", "status" : "online" }
跳過前3個檔案
db.test.find({}).skip(3)
結果:
{ "_id" : ObjectId("592516d7fbd5b591f53237b3"), "name" : "Sonny", "age" : "28", "status" : "away" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b4"), "name" : "Cher", "age" : "20", "status" : "online" }
按名稱欄位降序排序
db.test.find({}).sort({ "name" : -1})
結果:
{ "_id" : ObjectId("592516d7fbd5b591f53237b1"), "name" : "Tony", "age" : "25", "status" : "busy" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b3"), "name" : "Sonny", "age" : "28", "status" : "away" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b4"), "name" : "Cher", "age" : "20", "status" : "online" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b2"), "name" : "Bobby", "age" : "28", "status" : "online" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b0"), "name" : "Any", "age" : "21", "status" : "busy" }
計數結果數量
db.test.find({}).count()
結果:
5
組合使用這些方法
例如,取得排序後集合中跳過第1個檔案並限制傳回2個檔案的結果:
db.test.find({}).sort({ "name" : -1}).skip(1).limit(2)
結果:
{ "_id" : ObjectId("592516d7fbd5b591f53237b3"), "name" : "Sonny", "age" : "28", "status" : "away" }
{ "_id" : ObjectId("592516d7fbd5b591f53237b4"), "name" : "Cher", "age" : "20", "status" : "online" }
4.4 使用 AND、OR 和 IN 條件查詢檔案
students 集合中的所有檔案
db.students.find().pretty();
結果:
{
"_id" : ObjectId("58f29a694117d1b7af126dca"),
"studentNo" : 1,
"firstName" : "**Prosen**",
...
}
...
對應的 MySQL 查詢陳述式
SELECT * FROM students;
使用條件查詢
例如,查詢 firstName 為 “Prosen” 的學生:
db.students.find({firstName:"**Prosen**"});
對應的 MySQL 查詢陳述式:
SELECT * FROM students WHERE firstName = "**Prosen**";
AND 查詢
查詢 firstName 為 “Prosen",且 age 大於等於23的學生:
db.students.find({
"**firstName**": "**Prosen**",
"**age**": {
"$gte": 23
}
});
對應的 MySQL 查詢陳述式:
SELECT * FROM students WHERE firstName = "**Prosen**" AND age >= 23;
OR 查詢
查詢 firstName 為 “Prosen",或 age 大於等於23的學生:
db.students.find({
"$or": [{
"**firstName**": "**Prosen**"
}, {
"**age**": {
"$gte": 23
}
}]
});
對應的 MySQL 查詢陳述式:
SELECT * FROM students WHERE firstName = "**Prosen**" OR age >= 23;
MongoDB 查詢與更新操作深入解析
MongoDB 是一種 NoSQL 資料函式庫,其查詢與更新操作具有靈活性和高效性。本文將探討 MongoDB 的查詢與更新操作,包括 $or 查詢、$in 查詢、投影(Projection)、更新運算元(Update Operators)等。
$or 查詢與 $in 查詢
在 MongoDB 中,$or 查詢用於滿足多個條件中的至少一個。例如:
db.students.find({
firstName: "Prosen",
$or: [
{ age: 23 },
{ age: 25 }
]
});
上述查詢將傳回 firstName 為 “Prosen” 且 age 為 23 或 25 的檔案。對應的 MySQL 查詢陳述式為:
SELECT * FROM students WHERE firstName = "Prosen" AND (age = 23 OR age = 25);
而 $in 查詢則用於匹配某個欄位的值是否在給定的陣列中。例如:
db.students.find({ lastName: { $in: ["Ghosh", "Amin"] } });
上述查詢將傳回 lastName 為 “Ghosh” 或 “Amin” 的檔案。對應的 MySQL 查詢陳述式為:
SELECT * FROM students WHERE lastName IN ('Ghosh', 'Amin');
內容解密:
$or用於多條件查詢,只要滿足其中一個條件即可傳回結果。$in用於檢查某個欄位的值是否在給定的陣列中,提高了查詢的效率和可讀性。
投影(Projection)
投影是指在查詢結果中只傳回指定的欄位,而不是整個檔案。MongoDB 的 find() 方法支援投影操作。例如:
db.people.find({}, { age: 0 });
上述查詢將傳回所有檔案,但不包含 age 欄位。對應地,如果只想傳回 age 欄位,可以使用:
db.people.find({}, { age: 1 });
需要注意的是,預設情況下,_id 欄位總是會被傳回。如果不想傳回 _id,需要顯式指定:
db.people.find({}, { name: 1, _id: 0 });
內容解密:
- 投影操作允許開發者控制查詢結果中傳回的欄位,提高了資料處理的效率。
- 使用
1表示包含該欄位,使用0表示排除該欄位。
更新運算元(Update Operators)
MongoDB 提供了多種更新運算元,用於更新檔案中的特定欄位。其中,$set 是最常用的更新運算元之一。
例如,假設有一個 student 集合,需要將名字為 “Tom” 的學生的性別從 “M” 改為 “F”。如果直接使用以下更新陳述式:
db.student.update({ name: 'Tom' }, { sex: 'F' });
將導致整個檔案被替換,只剩下 sex 欄位。正確的做法是使用 $set:
db.student.update({ name: 'Tom' }, { $set: { sex: 'F' } });
這樣,只有 sex 欄位被更新,其他欄位保持不變。
內容解密:
$set更新運算元允許開發者更新檔案中的特定欄位,而不影響其他欄位。- 正確使用更新運算元可以避免意外覆寫其他重要資料。
MongoDB 聚合框架詳解
MongoDB 的聚合框架(Aggregation Framework)是一種強大的資料處理工具,能夠對資料進行複雜的處理和分析。本文將深入介紹 MongoDB 聚合框架的基本概念、使用方法和實際應用範例。
聚合框架基礎
聚合框架是一種根據管道(Pipeline)的資料處理模型。資料透過一系列的階段(Stage)進行處理,每個階段對資料進行特定的操作,如篩選、分組、排序等。
管道階段
聚合管道由多個階段組成,每個階段都有特定的功能。常見的階段包括:
$match:篩選資料,類別似於 SQL 中的WHERE子句。$group:分組資料,類別似於 SQL 中的GROUP BY子句。$project:投影資料,選擇需要的欄位。$sort:排序資料。$limit:限制輸出結果的數量。$unwind:展開陣列欄位。
實際應用範例
統計交易資料
假設我們有一個交易資料集合 transactions,包含欄位 cr_dr(交易型別)和 amount(交易金額)。我們可以使用聚合框架來統計不同交易型別的數量和總金額。
db.transactions.aggregate([
{
$group: {
_id: '$cr_dr',
count: {$sum: 1},
totalAmount: {$sum: '$amount'}
}
}
]);
輸出結果:
{
"_id": "C",
"count": 3,
"totalAmount": 120
}
{
"_id": "D",
"count": 5,
"totalAmount": 410
}
計算平均值
我們可以使用 $avg 聚合運算元來計算不同交易型別的平均金額。
db.transactions.aggregate([
{
$group: {
_id: '$cr_dr',
averageAmount: {$avg: '$amount'}
}
}
]);
輸出結果:
{
"_id": "C",
"averageAmount": 40
}
{
"_id": "D",
"averageAmount": 82
}
處理陣列資料
當我們需要處理陣列欄位時,可以使用 $unwind 階段來展開陣列。
db.inventory.aggregate([
{
$unwind: "$sizes"
}
]);
輸出結果:
{
"_id": 1,
"item": "myItem1",
"sizes": "S"
}
{
"_id": 1,
"item": "myItem1",
"sizes": "M"
}
{
"_id": 1,
"item": "myItem1",
"sizes": "L"
}