【MongoDB】使用操作符號來更新資料


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。

上一篇:【MongoDB】如何對陣列欄位進行查詢

下一篇:【MongoDB】使用聚合(aggregation)進行資料處理

留言