https://flic.kr/p/qakxAH
當在 MongoDB 進行 document 資料的更新時,筆者工作時最常見的做法是將 document 查詢出來,透過程式碼修改資料後,再呼叫 save 方法儲存回去。但除此之外,我們還可使用如同 SQL 的 UPDATE 指令來更新資料。
相較於 SQL 只能使用 SET 指令來設定欄位值,MongoDB 提供了許多實用的「操作符號」來幫助我們進行更新。本文會從官方文件中挑選幾種操作符號來示範用法,其中也包含對陣列欄位的處理。
一、updateMany 方法
除了使用 save 方法來儲存資料,我們還能使用 updateMany 方法直接更新 document。它接收兩個參數,分別是查詢條件與更新操作,藉此更新查詢到的所有 document。使用方式大致如下。
db.student.updateMany( // 查詢條件 { "欄位名稱": "欄位值" }, // 更新操作 { "操作符號": { "欄位名稱": "資料" } } )
該方法會回傳一個結果。matchedCount 代表符合查詢條件的 document 數量;而 modifiedCount 代表被更新的 document 數量。以下是範例結果。
{ "acknowledged": true, "matchedCount": 5, "modifiedCount": 2 }
關於查詢條件的撰寫,並不是本文的重點。在本文,我們假設要練習操作的 collection 叫做「student」,有著以下的初始資料。
且每一節的初始資料各自獨立。從下一節開始,筆者會介紹各種操作符號。
二、$set 操作符號
使用 $set 符號可以更新欄位的值。若欄位不存在,則視為新增欄位並給予該值。以下的範例是查出 name 欄位值為「Vincent」的資料,修改其 name 欄位值,並新增 birthday 欄位。
db.student.updateMany( { "name": "Vincent" }, { "$set": { "name": "Vincent Zheng", "birthday": ISODate("1996-01-01") } } )
三、$unset 操作符號
使用 $unset 符號可以移除指定欄位。以下的範例是移除所有 document 的 conductScore 欄位。
db.student.updateMany( {}, { "$unset": { "conductScore": "" } } )
關於 conductScore 的值給予空字串,MongoDB 的文件提到給予的值並不會影響操作。所以隨意給個值即可。
四、$rename 操作符號
使用 $rename 符號,可以修改欄位名稱。以下的範例是將所有 document 的 department 欄位,更名為 departments。
db.student.updateMany( {}, { "$rename": { "department": "departments" } } )
五、$inc 操作符號
使用 $inc 符號,可以將數值欄位的值增加我們想要的值。參數能給予正負整數或小數點。「inc」是「increase」的意思。以下的範例是將 grade 欄位值增加 1。
db.student.updateMany( {}, { "$inc": { "grade": 1 } } )
六、$max 操作符號
使用 $max 符號,可以在當傳入參數比 document 原本的欄位值還大時,將欄位值設為較大的參數。以下的範例是令 conductScore 的欄位值至少為 75。若已經大於等於 75 了,則保持不變。
db.student.updateMany( {}, { "$max": { "conductScore": 75 } } )
此例有兩個 document 會被更新,即 Dora 與 Winnie。
$max 符號還能用在日期欄位。除此之外,Mongo DB 尚提供 $min 符號可使用。
七、$push 操作符號
使用 $push 符號,可以新增一筆資料至陣列欄位中。若欄位不存在,則視為新增欄位並給予包含該元素的陣列。以下的範例是在 department 欄位中新增「通識」這個字串。
db.student.updateMany( {}, { "$push": { "department": "通識" } } )
如果陣列中存放的元素是物件,那麼只要將想要新增的物件做為參數傳入即可。以下的範例是在 courses 欄位新增一個課程物件。
db.student.updateMany( {}, { "$push": { "courses": { "name": "體育", "point": 0 } } } )
八、$addToSet 操作符號
使用 $addToSet 符號,可以新增一筆資料至陣列欄位中。但若該資料已存在於陣列中,則不會對該 document 更新。以下的範例是針對 department 包含「財務金融」的 document,在其 courses 欄位新增一個課程物件。
db.student.updateMany( { "department": "財務金融" }, { "$addToSet": { "courses": { "name": "財金概論", "point": 3 } } } )
此例有兩個 document 符合查詢條件,即 Vincent 與 Dora。但 Dora 的 courses 陣列中已經有完全相同的物件了,因此只有 Vincent 會被更新。
九、$each 操作符號
在使用 $push 或 $addToSet 符號時,若想一次新增多筆資料到陣列欄位,並不是直接將新資料組成陣列後傳入。而是要搭配 $each 符號,才將新資料的陣列做為參數傳入。以下的範例是對 department 欄位新增「通識」和「體育」兩個字串。
db.student.updateMany( {}, { "$push": { "department": { "$each": ["通識", "體育"] } } } )
十、更新陣列中的物件
如果想要更新陣列元素的某個欄位,需要額外使用叫做「positional all」的符號。使用 $[] 符號,可以在描述要更新的欄位時,用來表示陣列中的每個元素。以下的範例是令 courses 陣列中的物件,其 point 欄位至少為 2。
db.student.updateMany( {}, { "$max": { "courses.$[].point": 2 } } )
此例有兩個 document 會被更新,即 Vincent 與 Winnie。
留言
張貼留言