本文地址:http://www.cnblogs.com/egger/archive/2013/05/01/3053617.html 歡迎轉載 ,請保留此鏈接๑•́ ₃•̀๑!
通常文檔只會有一部分要更新。利用原子的更新修改器,可以使得這種部分更新極為髙效。更新修改器是種特殊的鍵,用來指定復雜的更新操作,比如調整、增加或者刪除鍵,還可能是操作數組或者內嵌文檔。
字段更新操作符 Field Update Operators
$set
"$set"用來指定一個鍵的值。如果這個鍵不存在,則創建它。
我們往下面的一條用戶資料添加“興趣”信息,
db.users.insert({"name":"egger", "age": 28, "sex" : "male"})

運行下面的代碼,將該用戶的興趣設置為“讀書”並添加至文檔中(此時文檔中“hobby”鍵是不存在,該條文檔就會創建它):
db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},
{"$set" : {"hobby" :"read"}} )

當想更改用戶的興趣資料時,使用"$set" 然后將要更新的內容作為鍵“hobby”的值(下面的示例中將數組作為鍵值):
db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},
{"$set" : {"hobby" :["swimming","basketball"]}} )
用"$set"甚至可以修改鍵的數據類型
db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},{"$set" : {"sex" :1 }} )
執行結果如下:

使用"$set"修改內嵌文檔:

該文檔中的作者信息為內嵌文檔,我們將其內容全部更改:
db.posts.update({"author.name":"egger"},{"$set":{"author.name":"mongo","author.age":18}})

$unset
從文檔中移除指定的鍵。
若要完全刪除鍵“hobby”,使用“$unset”即可:
db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},{"$unset" : {"hobby" :1 }} )

$inc
"$inc"修改器用來增加已有鍵的值,或者在鍵不存在時創建一個鍵。$inc就是專門來增加(和減少)數字的。"$inc"只能用於整數、長整數或雙精度浮點數。要是用在其他類型的數據上就會導致操作失敗。
例如毎次有人訪問該博文,該條博文的瀏覽數就加1,用鍵"pageviews"保存瀏覽數信息。

下面使用"$inc”修改器增加"pageviews"的值
db.posts.update({"_id" : ObjectId("5180f1a991c22a72028238e4")}, {"$inc":{"pageviews":1}})

上面執行update時如果將鍵值設置為n,那么就表示該鍵的值增加n(n可以為負數)。
db.posts.update({"_id" : ObjectId("5180f1a991c22a72028238e4")}, {"$inc":{"pageviews":-100}})

$rename
語法: {$rename: { <old name1>: <new name1>, <old name2>: <new name2>, ... } }
$rename操作符可以重命名字段名稱,新的字段名稱不能和文檔中現有的字段名相同。
如果文檔中存在A、B字段,將B字段重命名為A,$rename會將A字段和值移除掉,然后將B字段名改為A.
集合students中的一條文檔數據:
{ "_id": 1,
"nickname": [ "The American Cincinnatus", "The American Fabius" ],
"cell": "555-555-5555",
"name": { "first" : "george", "last" : "washington" }
}
將集合中"nickname"字段名重命名為“alias”、"cell"字段名重命名為"mobile":
db.students.update( { _id: 1 }, { $rename: { 'nickname': 'alias', 'cell': 'mobile' } } )

執行下面的更新操作,集合中已存在name字段,將會刪除“name”字段,將“alias”字段名重命名為“name”
db.students.update( { _id: 1 }, { $rename: { "alias": "name" } } )

當重命名子文檔字段名時需要使用"."操作符,格式:值為該子文檔的字段名.子文檔中字段名。
db.students.update( { _id: 1 }, { $rename: { "name.first": "name.fname" } } )
執行上面的更新操作將name字段的值中first字段重命名為fname.

$rename操作符也可以將子文檔中鍵值移到其他子文檔中。
db.students.update( { _id: 1 }, { $rename: { "name.last": "contact.lname" } } )
我們將名為name的子文檔中的last字段,重名為“lname”,同時將其移動到子文檔contact中,若contact字段不存在,數據庫會新建該字段。

若指定的字段在集合中不存在,$rename操作符將不會有任何影響。
db.students.update( { _id: 1 }, { $rename: { 'wife': 'spouse' } } )
若指定的多個字段在集合中都不存在,$rename操作符將不會有任何影響。
db.students.update( { _id: 1 }, { $rename: { 'wife': 'spouse', 'vice': 'vp', 'office': 'term' } } )
集合中不存在上面語句中指定的wife、vice、office字段,所以上述的更新操作無任何影響。
若指定的多個字段中,有的在集合中存在,有的不存在,$rename操作符執行下列操作:
- 存在的字段按照上面的規則重命名為新的名稱。
- 不存在的字段對數據無任何影響。

db.students.update( { _id: 1 }, { $rename: { 'wife': 'alias', 'mobile': 'cell' } } )
執行上述更新操作,文檔中只有“mobile”字段被替換為“cell”。

upsert
upsert是一種特殊的更新操作,不是一個操作符。(upsert = up[date]+[in]sert)
update() 方法的三個參數是upsert,這個參數是個布爾類型,默認是false。當它為true的時候,update方法會首先查找與第一個參數匹配的記錄,在用第二個參數更新之,如果找不到與第一個參數匹配的的記錄,就會以這個條件和更新文檔為基礎創建一個新的文檔。如果找到了匹配的文檔,則正常更新。upsert非常方便,不必預置集合,同一套代碼可以既創建又更新文檔。
db.users.remove() db.users.update({age :25}, {$inc :{"age" :3}}, true) db.users.findOne()
我們將users集合清空,執行upsert操作,查詢出age字段值為25的文檔,然后將該字段值增加3.
由於我們先清空了集合,所以update操作將執行insert操作,先創建一個鍵“age”的值為25的文檔,然后在將這個值增加3,即鍵“age”的值為28,如圖所示.

$setOnInsert
當update方法使用upsert選項執行insert操作時,$setOnInsert操作符給相應的字段賦值。類似sql中update 語句的set。
db.collection.update( <query>, { $setOnInsert: { <field1>: <value1>, ... } }, { upsert: true } //{ upsert: true }可以用true替換 )
示例:products集合無任何文檔,執行下列語句,將插入一條文檔"{ "_id" : 1, "defaultQty" : 100 }":
db.products.update( { _id: 1 }, { $setOnInsert: { defaultQty: 100 } }, { upsert: true } )

若update方法執行的update操作而不是insert操作,那么$setOnInsert操作符將無效。
集合中有如下一條文檔: { "_id" : 1, "defaultQty" : 100 }
下面的update方法將執行update操作:
db.products.update( { _id: 1 }, { $setOnInsert: { defaultQty: 500, inStock: true }, $set: { item: "apple" } }, { upsert: true } )
更新結果,$setOnInsert沒有任何影響。

數組更新操作符 Array Update Operators
只能用在鍵值為數組的鍵上的數組操作。
$ (query)
語法: { "<array>.$" : value }
當對數組字段進行更新時,且沒有明確指定的元素在數組中的位置,我們使用定位操作符("$")標識一個元素,數字都是以0開始的。
和update()一起使用:
- 定位操作符("$")作為第一個匹配查詢條件的元素的占位符,也就是在數組中的索引值。
- 數組字段必須出現查詢文檔中。
集合students中有兩條文檔:
{ "_id" : 1, "grades" : [ 78, 88, 88 ] }
{ "_id" : 2, "grades" : [ 88, 90, 92 ] }
執行下列語句創建集合文檔數據:
db.students.remove(); db.students.insert({ "_id" : 1, "grades" : [ 78, 88, 88 ] }); db.students.insert({ "_id" : 2, "grades" : [ 88, 90, 92 ] });
執行下列操作:
//查詢匹配的文檔中,數組有2個88,只更新第一個匹配的元素,也就是"grades.1" db.students.update( { _id: 1, grades: 88 }, { $set: { "grades.$" : 82 } }) ; //查詢文檔中沒有出現grades字段,查詢報錯 db.students.update( { _id: 2 }, { $set: { "grades.$" : 82 } } );

"$push"修改器
如果指定的鍵已經存在,會向已有的數組末尾加入一個元素,要是沒有就會創建一個新的數組。
下面是一條文章內容的文檔數據:

我們將使用"$push"對該文檔添加一條評論信息。。
db.posts.update({"title":"MongoDB"},{$push:{"comments":{"name":"egger","content":"thks!"}}})
$push 沒有使用雙引號。文檔將會增加一個"comments"(評論)鍵且鍵值是數組類型的。
繼續添加一條評論信息,該信息將添加至鍵值數組的末尾。
db.posts.update({"title":"MongoDB"},{$push:{"comments":{"name":"egger","content":"thks 2!"}}})

$pull
語法:db.collection.update( { field: <query> }, { $pull: { field: <query> } } );
$pull操作符移除指定字段值為數組,且匹配$pull語句聲明的查詢條件的所有元素。
//插入一條文檔 db.profiles.insert({ votes: [ 3, 5, 6, 7, 7, 8 ] }); //移除數組中所有元素7 db.profiles.update( { votes: 3 }, { $pull: { votes: 7 } } ); //移除數組中所有大於6的元素 db.profiles.update( { votes: 3 }, { $pull: { votes: { $gt: 6 } } } ); //Result { votes: [ 3, 5, 6, 8 ] } { votes: [ 3, 5, 6 ] }

內容參考:
1.http://docs.mongodb.org/manual/reference/operator/
