MongoDB Certification Study Guide / MongoDB 證照考試指南 重點整理(上)

Caspar Chang
15 min readMar 18, 2021

本文是 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 記得多做,可以幫助你大致了解考試題型以及比較不足的地方,也比較好做針對性的補強。

記得準備 Certification Study Guide

接下來會帶著大家複習考試要點,這是我在準備認證的時候整理的Study Guide,會從中挑出比較重要的部分跟大家做分享。

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, $lte
Logical
$and, $or
Element
$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 lock
Index 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 / rejectedPlans
executionStats
呈現執行狀況, totalDocsExamined / totalKeysExamined/ nReturned/ executionTimeMillis
allPlansExecution
顯示部分拒絕的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 key
Collation, 可以建立 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代替sparse
Hidden, 不會被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運算後合成一個新的值

--

--

Caspar Chang

具有十年以上的資料庫開發與維運管理經驗,現任職於 MongoDB Taiwan 解決方案架構師