MongoDB 文檔的更新操作


在MongoDB中,更新單個doc的操作是原子性的。默認情況下,如果一個update操作更新多個doc,那么對每個doc的更新是原子性的,但是對整個update 操作而言,不是原子性的,可能存在前面的doc更新成功,而后面的doc更新失敗的情況。由於更新單個doc的操作是原子性的,如果兩個更新同時發生,那么一個更新操作會阻塞另外一個,doc的最終結果值是由時間靠后的更新操作決定的。

通過使用 $isolated option,能夠確保更新多個doc的寫操作是原子性的,任何查詢操作都會讀取到更新操作,直到該操作完成(成功或失敗)。 

Prevents a write operation that affects multiple documents from yielding to other reads or writes once the first document is written. By using the $isolated option, you can ensure that no client sees the changes until the operation completes or errors out.

MongoDB在新增和更新數據的時候,不會實時寫入到Disk中,可能會丟失數據。

一,語法

默認情況下,update只會更新single doc,如果需要更新多個doc,必須顯式設置doc: multi:true。

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)

upsert:Optional. If set to true, creates a new document when no document matches the query criteria. The default value is false, which does not insert a new document when no match is found.

multi:Optional. If set to true, updates multiple documents that meet the query criteria. If set to false, updates one document. The default value is false.

二,更新示例

在users collection中有三個doc,插入代碼如下

user1={ name:"t1", age:21}
user2={ name:"t2", age:22}
user3={ name:"t3", age:23}

db.users.insert([user1,user2,user3])

1,upsert option usage

upsert option的含義是,如果collection中存在匹配的doc,那么更新該doc;如果不匹配任何doc,那么插入一條新的doc。

使用update命令和 upsert選項,插入一條新的user,name=“t4”

db.users.update({name:"t4"},{name:"t4"},{upsert:true})

對新插入的user新增field:age=24,必須將doc的所有field都顯式指定。

db.users.update({age:24},{name:"t4",age:24})

如果在Update doc中,只包含age=24,那么將失去name field,例如

 db.users.update({name:"t4"},{age:24})

2,multi option usage

在使用multi option更新多個doc之前,先考慮一個問題,如果把age的年紀都加1,那么在age加1時,保持其他field不變。這種情況需要用到$inc operator,用於將指定字段的值遞增,同時不會影響其他字段。

{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }

示例,將符合條件的User的age 加 1

db.users.update({age:{$lt:24}},{$inc:{age:1}},{multi:true})

3,為所有的user 增加字段

這種scenario需要用到$set operator,用於替換指定字段的值,或新增字段。

{ $set: { <field1>: <value1>, ... } }

The $set operator replaces the value of a field with the specified value. If the field does not exist, $set will add a new field with the specified value, provided that the new field does not violate a type constraint. If you specify a dotted path for a non-existent field, $set will create the embedded documents as needed to fulfill the dotted path to the field.

示例,為所有的user增加sex字段,默認值是femal。

db.users.update({},{$set:{sex:"femal"}},{multi:true})

三,原子更新multiple doc

在query filter中加入 $isolated:1,表示對於查詢到的所有doc,update操作將會在一個原子操作中完成。

db.users.update({$isolated:1},{$set:{sex:"femal"}},{multi:true})

四,更新doc的結構

1,將doc的sex field刪除

Step1,使用FindOne找到name=t4的User

t4=db.users.findOne({name:"t4"})

Step2,使用delete command 刪除sex field

delete t4.sex;

Step3,使用Updae 替換原來的doc

 db.users.update({name:"t4"},t4);

step4,使用find 查看doc的數據更新

2,使用db.collection.replaceOne替換doc

db.collection.replaceOne(
   <filter>,
   <replacement>,
   {
     upsert: <boolean>,
     writeConcern: <document>
   }
)

step1,使用findOne()查找一個doc

 t4=db.users.findOne({name:"t4"})

step2,為doc增加一個sex field

t4.sex="femal"

step3,使用replaceOne函數替換doc

db.users.replaceOne({name:"t4"},t4)

3,使用$set對所有符合query filter的doc批量修改doc結構

db.users.update({age:{$lte:23,$gte:21}},{$set:{sex:"femal"}},{multi:true});

4,使用$unset對所有符合query filter的doc批量刪除doc的field

db.users.update({$and:[{age:{$lte:23}},{age:{$gte:21}}]},{$unset:{sex:"femal"}},{multi:true})

--or 
db.users.update({age:{$lte:23,$gte:21}},{$set:{sex:"femal"}},{multi:true});

 

 

參考doc:

Update Documents

Atomicity and Transactions

$isolated

$set


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM