MongoDB Certification Study Guide / MongoDB 證照考試指南 重點整理(上)
本文是 MongoDB Certified Study Guide(上),主要分享認證考試重點,幫助大家快速應試考取證照。
由於內容較多,本篇僅介紹 Philosophy and Features, CRUD, Indexes 與 Aggregation (Developer Only)。
其餘的包括 Replication, Sharding, Application & Server Administration (DBA Only), Storage Engine, Glossary 請參考下篇。
MongoDB Certified Intro 請參考於此。
MongoDB Certified Overview 請參考於此。
開始之前
Practice Exams 記得多做,可以幫助你大致了解考試題型以及比較不足的地方,也比較好做針對性的補強。
Philosophy and Features
概述
大概會出4題, 主要都是基本知識與名詞解釋,練習題多做幾遍就差不多了。
BSON與JSON :
BSON 是Binary JSON, 可以處理更多資料型態如32-bit integer, 64-bit integer, Decimal128, timestamp。
_id (ObjectID) :
自動產生,新增空白文檔也會有ObjectID的存在
values are 12 bytes in length無法被更改,包含$replaceOne也無法更改。
Transaction :
MongoDB 4.0 提供 Replicaset transaction, 沒有 Sharding transaction單個Transaction沒有文檔數限制,預設60秒時間,超時Transaction自動還原
transactionLifetimeLimitSeconds : 60s for default have lifetime
Cursor :
cursor.maxTimeMS(ms) => process time limit, no defaultcursor.noCursorTimeout() => idle time limit, default 10 minutescursor.batchSize=> 查詢一次性回傳的筆數, default on mongo shell is 20,
超過20筆資料 需使用 getMore (it) 指令iterate
CRUD
概述
大概會出10題, 請務必熟悉 db.collection.find() 等語法與格式
考題主要是給你看一段語法,讓你判斷結果會是什麼
例如: db.people.find(...)
或是: db.people.updateMany(...)
以下是個人整理出常見的 statement 與 operator 提供參考
Statement :
find
回傳為cursor, 指定 projection { year: 1 } 例如以下
db.movies.find( { genre: "Action" }, { year: 1 } )
{_id: 0, year: 1} 才不會回傳_id值findOne
回傳為document, 預設回傳未排序的第一筆資料, 等同 sort( { $natural:1 } )updateOne & replaceOne
update : 更改指定欄位
replace : 替換整個文檔insertMany & bulkWrite
預設是 ordered,順序匯入,stop on error
使用 unordered,平行匯入,error的跳過,其他繼續
Operator :
Comparison
$eq, $gt, $gte, $lt, $lteLogical
$and, $orElement
$exists, 判斷是否存在, null value也算存在Evaluation
$regex, 正則判斷
start with a : /^a/, /^a.*/
end with 789 : /789$/, /.*789$/
case insensitive ABC : /^ABC/i
$text, 查詢的時候只要有出現過都會被查詢到
{ $search : "fact find" }, fact or find 出現都算
$near, geo使用, 知道就好Update
$inc
$set, 修改欄位值,如果欄位不存在則新增
$unset, 移除欄位職,如果欄位不存在則什麼都不做
$mul, 需注意不同的數字型態相乘會有不同的結果
例如 Mul NumberLong(10) by NumberInt(5) = NumberLong(50)
Operator for array :
Query
[array.$], 對矩陣任何一個位置指定查詢
[array.1], 對矩陣第二個位置指定查詢
$all 矩陣的內容都要符合. and的意思
{ tags: { $all: [ "ssl" , "security" ] } }
等同於 { $and: [ { tags: "ssl" }, { tags: "security" } ] }
$elemMatch : 跟all類似,但有更多表示方式 例如 大於80 小於85
$in : 矩陣的內容部分符合. or的意思
$size : 矩陣大小Update
$push : 將值新增至矩陣
$pull : 將值從矩陣移除
$addtoSet : 新增至矩陣,如果值已存在矩陣則不動作
Cursor :
skip() & limit()
$skip 10 + $limit 5 改成成 $limit 15 + $skip 10 效能會比較好sort()
預設為1, 從小到大
排序規則先data type,然後value
type : null first, array last
INDEX
概述
大概會出8題, 主要考index的運作原理,使用index的優缺點
查詢是否能用到index, 如何確認使否使用到index? (explain的內容是什麼)
Compound Indexes大概是最常考的, 欄位排序與正向反向
以及確保ESR Rule, 避免sort in memory
最後就是index的種類與進階用法,可以大概參考以下分享
Index basics :
Intro :
佔用硬碟/記憶體空間,讓寫入速度變慢,查詢速度提高
建立index的開始與最後會對collection有短暫的exclusive lockIndex type : B+ Tree (B Tree)Default Index : _id, Unique指定使用 Index : db.find().hint({name:1})
Index rules :
ESR Rule (Equaluty, Sort and Range)
查詢的時候,查詢條件符合ESR順序會讓查詢效果最好 (完全使用到Index)

Covered Quiries :
能夠用最快的方式查詢資料,限定查詢時只project有在index裡面資料現有index : { rating: 1, price: 1 }查詢語法 : db.products.find( { "rating": { "$gt": 7 } }, { "_id": 0, "price": 1 } )不支援Array&Embedded!!!
Cursor Explain :
queryPlanner (default)
顯示 winningPlan / rejectedPlansexecutionStats
呈現執行狀況, totalDocsExamined / totalKeysExamined/ nReturned/ executionTimeMillisallPlansExecution
顯示部分拒絕的plan
Indexes :
Single Field Indexes
index : { "item": 1}Compound Indexes, 前後順序很重要, order也很重要
index : { "item": 1, "location": 1, "stock": 1 }
對於查詢 { item: 1 } 或是 { item: 1, location: 1 } 都有幫助
對於查詢 { location: 1, item: 1 } 或是 { item: -1, location: 1 } 沒有幫助Multikey Indexes, 可以對Array建立Index, 一次最多一個Array Filed
一個Array有四個值,就會建立四組索引Geospatial IndexesText Indexes, 查詢時大小寫不分
createIndex( { comments: "text" } )Wildcard Indexes
createIndex( { "$**" : 1 } ), 只能為Single Field, 單欄位Hashed Indexes
createIndex( { "filed": "hashed" } )
Indexes Properties :
TTL, 只能在 Single Field Indexes 生效
createIndex( { "ModifiedDate": 1 }, { expireAfterSeconds: 60 } )
當TTL建立後就會開始刪除過期資料,注意是每60秒背景刪除, 所以資料有可能留存一小段時間直到刪除完成Unique, 可以在 Compound indexes 生效
createIndex( pid, { unique: true } )
如果要在分片中使用,index prefix 必需包含 shard keyCollation, 可以建立 case insensitive index
createIndex( { type: 1}, { collation: { locale: 'en', strength: 2 } } )
查詢時亦要指定collation, 以指定的collation判斷回傳結果
find( { type: "apple" } ).collation( { locale: 'en', strength: 2 } )Partial, 不能建立在_id或是shard key
createIndex( { cuisine: 1 }, { partialFilterExpression: { rating: { $gt: 5 } } } )
查詢條件必須與index一樣,
find( { cuisine: "Italian", rating: { $gte: 8 } } )Sparse, 只會對有field欄位的record建立索引, null value也會建立
建議使用partial代替sparseHidden, 不會被query planner看到, 所以不會幫助查詢, 亦無法使用 hint()指定
透過 hideIndex / unhideIndex 來實現
如果hidden index 有 unique / TTL 屬性, 此類功能依然生效
Aggregation (Developer Only)
概述
大概會出10題, 主要考法類似CRUD, 一樣給你看一段語法,讓你判斷結果會是什麼
但由於aggregation語法較為複雜, stage 與 operator 種類繁多, 常常會看很久
需要花點心思熟悉格式, 至少可以一眼就可以看懂下列的語法, 避免考試時間不夠
所以最常見的 $match, $group, $unwind 請務必熟悉
這段也是Developer認證中最容易落馬的部分//訂單的金額按照客戶id做加總
db.orders.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])//找出人口加總過千萬
db.zipcodes.aggregate( [
{ $group: { _id: "$state", totalPop: { $sum: "$pop" } } },
{ $match: { totalPop: { $gte: 10*1000*1000 } } }
] )//找出排名前五的likes, 先做拆分, 再分組把次數做加總, 再排序, 再找出Top5
db.users.aggregate([
{ $unwind : "$likes" },
{ $group : { _id : "$likes" , number : { $sum : 1 } } },
{ $sort : { number : -1 } },
{ $limit : 5 }
])
Aggregation basic :
限制:單個aggregation 只能有 100MB記憶體使用量 或是設定allowDiskUse只出現一次
$out, $merge, and $geoNear只在 last stage 出現
$out, $merge只在 first stage 出現
$collStats / $indexStat只在 Primary Shard 執行
$out, $lookup / $graphlookup, $facet
其餘的例如$group 會在random shard單一的aggregation
count(), estimatedDocumentCount(), distinct()
Operators for stages :
$match, 裡面只能下query,如同find()
基本上find()裡面有的參數也都能夠運用, 例如hint()$addFields($set), 如果Field已存在,亦可以當作$set使用$project/$unset, add/remove fileds, project : 0 等同 unset$unwind, 對embed文檔做拆分,由一筆文檔拆成多筆文檔
source : insertOne({ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] })
operation : { $unwind : "$sizes" }
result : { "_id" : 1, "item" : "ABC1", "sizes" : "S" }, { "_id" : 1, "item" : "ABC1", "sizes" : "M" }, { "_id" : 1, "item" : "ABC1", "sizes" : "L" }$group
{ $sum : 1 } 代表次數加總
{ $sum : "$amount"} 代表值加總$lookup, 只能在自己的db, 對象collection必須為unshard
參考 : from, foreignField, localField, as(new field)$graphLookup, 只能在自己的db, 對象collection必須為unshard
參考 : from, startWith, connectFromField, connectToField, maxDepth (0 to N), depthFiled (階層, long) ...$out, 將aggregation的結果寫入到另一個collection
MongoDB 4.4開始可以在不同db, 對象必須為unshard
operation : $out: { db: "<output-db>", coll: "<output-collection>" }$merge, 將aggregation的結果寫入到另一個collection
可以在不同db, 可以為shard collection
{ $merge: { into: "myOutput", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }
簡易替代用法
{ $merge: <collection> } // Output collection is in the same database$sortByCount, 等同於一次進行 group + sort 兩個 stage$bucket, groupBy, boundaries (最少兩個數值),將用戶用年齡區分
operatioin : $bucket: { groupBy: "$year_born", boundaries: [ 1980, 1990, 2000], default: "other"
在區間以外的 都會被分到 other, 不設定default會報錯$facet, multiple pipeline ($bucket/$sortByCount) in one stage, 不能夠巢狀 (nest) 使用
operation : $facet: { "price": [ { $bucketAuto …} ], "year": [ { $bucketAuto …} ] }$sample
隨機回傳指定數量3的文件, { $sample: { size: 3 } }$replaceRoot / $replaceWith, 使用即時產生的新文檔取代舊文檔
Operator for expressions :
$concat, 將多字串組合成一串文字,但如果其中一個字串是null, 結果就會是null
source : { "_id" : 1, "item" : "ABC1", quarter: "13Q1", "description" : "product 1" }
operation : $concat: [ "$item", " - ", "$description" ]
result : { "_id" : 1, "itemDescription" : "ABC1 - product 1" }$split, 將字串轉為矩陣
Operator for expressions for array :
$slice
取矩陣第0個數字位置開始n個數值的子集合, n為正數則前向後,n為負數後向前$filter
透過條件過濾矩陣子集合,例如帶出item.price>100的所有items (id, name, price)$arrayElemAt
回傳矩陣數字位置的內容值,從0開始,負數代表倒著數$indexOfArray
內容值在矩陣中的數字位置,從0開始, 可以有起訖$map
對矩陣的每個值做運算,矩陣維持不變$reduce
將矩陣消失,搭配inivalue運算後合成一個新的值