學習Mongodb筆記(三)——文件更新中高效的修改器
在MongoDB中,經常會對於文件進行更新,最簡單的更新是用一個新文件完全替換匹配的文件,但是通常我們會對於一小部分更新,所以我們就需要使用原子性的更新修改器,指定對於文件中末些欄位進行更新,更新修改器是種特殊的建,用來指定複雜的更新操作,如修改,新增或者刪除鍵,還可能是運算元組或者內嵌文件。
1. $set修改器
$set 修改器用來指定一個鍵值。如果這個鍵不存在,則建立他,他對更新模式或者使用者定義鍵來說非常方便。
> db.users.findOne() { "_id" : ObjectId("56fe7df8b322e3ff1dabf834"),"name" : "joe", "age" : 30, "sex" : "male", "location" : "Wisconsin", "favorite book" : "war and pace" } > db.users.update({"name":"joe"},{"$set":{"favorite book":["cat's cardle","foundation trilogy","ender's game"]}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.findOne() { "_id" : ObjectId("56fe7df8b322e3ff1dabf834"), "name" : "joe", "age" : 30, "sex" : "male", "location" : "Wisconsin", "favorite book" : [ "cat's cardle", "foundation trilogy","ender's game" ] }
$unset修改器
$unset修改用於將鍵刪除
> db.users.findOne() { "_id" : ObjectId("56fe7df8b322e3ff1dabf834"), "name" : "joe", "age" : 30, "sex" : "male", "location" : "Wisconsin", "favorite book" : [ "cat's cardle", "foundation trilogy", "ender's game" ] } > db.users.update({"name":"joe"},{"$unset":{"favorite book":1}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.findOne() { "_id" : ObjectId("56fe7df8b322e3ff1dabf834"), "name" : "joe", "age" : 30, "sex" : "male", "location" : "Wisconsin" }
$inc修改器
$inc其用來增加或減少已有的鍵的鍵值,或者在鍵不存在的時候建立一個鍵。
> db.games.insert({"game":"pinball","user":"joe"}) WriteResult({ "nInserted" : 1 }) > db.games.findOne() { "_id" : ObjectId("5770a1394f533aa7535d46d4"), "game" : "pinball", "user" : "joe" } > db.games.update({"game":"pinball","user":"joe"},{"$inc":{"score":50}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.games.findOne() { "_id" : ObjectId("5770a1394f533aa7535d46d4"), "game" : "pinball", "user" : "joe", "score" : 50 }
以上"$inc"與"$set"的用法類似,就是專門用來增加或減少數字的。"$inc"只能用於整數、長整數或雙精度浮點數,要是在其他型別的資料上就會導致操作失敗,其中包括很多語言會自動轉換成數字的型別,例如null,布林型別,或數字構成的字串。"$inc"鍵的值必須為數字,不能使用字串、陣列和其他非數字的值,否則會報錯,要修改其他型別,只能使用"$set"。
如下:
> db.foo.insert({"count":"1"}) WriteResult({ "nInserted" : 1 }) > db.foo.find() { "_id" : ObjectId("5770befc4f533aa7535d46d5"), "count" : "1" } > db.foo.update({},{"$inc":{"count":1}}) WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 16837, "errmsg" : "Cannot apply $inc to a value of non-numeric type. {_id: ObjectId('5770befc4f533aa7535d46d5')} has the field 'count' of non-numeric type String" } }) > db.foo.update({},{$set:{count:2}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.foo.find() { "_id" : ObjectId("5770befc4f533aa7535d46d5"), "count" : 2 } >
陣列修改器 $push
陣列修改器,顧名思義它只可以用於運算元組,只能用在值為陣列的鍵上。$push修改器如果指定的值已經存在,"$push"會想已有的陣列末尾加入一個元素,要是沒有就會建立一個新的陣列。
> db.blog.findOne() { "_id" : ObjectId("57709da84f533aa7535d46d3"), "title" : "a blog post", "author" : { "name" : "joe schmoe op", "email" : "[email protected]" } } > db.blog.update({"title":"a blog post"},{"$unset":{"author":1}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.blog.findOne() { "_id" : ObjectId("57709da84f533aa7535d46d3"), "title" : "a blog post" } > db.blog.update({"title":"a blog post"},{"$push":{"comments":{"name":"joe","email":"[email protected]","content":"nice post"}}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.blog.findOne() { "_id" : ObjectId("57709da84f533aa7535d46d3"), "title" : "a blog post", "comments" : [ { "name" : "joe", "email" : "[email protected]", "content" : "nice post" } ] }陣列修改器 $ne
$ne也是用來運算元組的修改器,在查詢文件中,如果一個值不在數組裡面就把他加進去,如果在不新增。
> db.users.insert({"name":"joe","emails":["[email protected]","[email protected]","[email protected]"]}) WriteResult({ "nInserted" : 1 }) > db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]" ] } > db.users.update({"name":"joe","emails":{$ne:"[email protected]"}},{$push:{"emails":"[email protected]"}}) WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 }) --nMatched為0表示沒有修改 > db.users.update({"name":"joe","emails":{$ne:"[email protected]"}},{$push:{"emails":"[email protected]"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]", "[email protected]" ] }
以上這種方式也可以使用$addToSet實現。
陣列修改器 $addToSet
$addToSet也是用來運算元組的修改器,實現的功能與$ne修改器相同,且更為方便。使用$addToSet修改器可以避免重複。
> db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]", "[email protected]" ] } > db.users.update({"_id":ObjectId("5770ca42e90c1adc80040a08")},{$addToSet:{"emails":"[email protected]"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 }) --原文件裡已有"[email protected]",修改完也沒有產生重複值 > db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]", "[email protected]" ] } > db.users.update({"_id":ObjectId("5770ca42e90c1adc80040a08")},{$addToSet:{"emails":"[email protected]"}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]", "[email protected]itpub.com", "[email protected]" ] }
陣列修改器 $each
$each陣列修改器要和$addToSet修改結合起來用,可以一次新增多個不同的值。例如上面的例子中,我們一次新增多個email值, 如下:
> db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]" ] } > db.users.update({"_id":ObjectId("5770ca42e90c1adc80040a08")},{$addToSet:{$each:["[email protected]","[email protected]","[email protected]"]}}) WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 52, "errmsg" : "The dollar ($) prefixed field '$each' in '$each' is not valid for storage." } }) > db.users.update({"_id":ObjectId("5770ca42e90c1adc80040a08")},{$addToSet:{"emails":{$each:["[email protected]","[email protected]","[email protected]"]}}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]" ] } >
陣列修改器 $pop
$pop修改器主要於從陣列中刪除元素,他可以從陣列中的任何一端刪除元素,
例如:
{$pop:{key:1}} 從陣列末尾刪除一個元素
{$pop:{key:-1}} 從陣列頭部刪除一個元素
> db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]" ] } > db.users.update({"name":"joe"},{$pop:{"emails":1}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]" ] } > db.users.update({"name":"joe"},{$pop:{"emails":-1}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.findOne() { "_id" : ObjectId("5770ca42e90c1adc80040a08"), "name" : "joe", "emails" : [ "[email protected]",