MongoDB 文檔字段增刪改

MongoDB
基於CRUD(create,read,update,delete)方式實現了對集合上的文檔進行增刪改查。對於集合上字段的增刪改,可使用set或者unset修改器來實現。也可使用文檔替換的方式來實現。本文主要描述集合上字段的增刪改,以及基於選項upsert的更新。php

關於MongoDB文檔更新能夠參考:MongoDB 文檔更新mysql

1、語法描述sql

db.collection.update(
   <query>,                  //查詢或過濾條件
   <update>,                 //修改器(被修改鍵及內容)
   {                         
     upsert: <boolean>, //爲true/false,true時未找到匹配文檔則建立新文檔
     multi: <boolean>,       //用於肯定是單行仍是更新全部行(true爲全部行)
     writeConcern: <document>   //設定寫關注,用於確保強一致性仍是弱一致性
   }                            //後面的3.2以後的語法參數基本相同
)

其餘的如updateOne,updateMany等用法請參考:MongoDB 文檔更新

MongoDB集合上全部的寫操做特性:
 原子性操做(單個文檔級別原子性操做)
 _id 字段沒法修改,即沒法使用一個新的_id值來代替
 因爲更新致使文檔尺寸超出預期分配的情形,會自動調整填充因子,從新分配空間
 保留文檔字段的順序,可是更新或重命名可能致使字段順序從新排序(_id老是文檔第一個字段)

2、update的幾個經常使用修改器數組

一、文檔更新($set修改器常規更新)markdown

//$set修改器最經常使用,等同於RDBMS update的set子句
//演示重用的的示例集合數據請參考:mongoDB 比較運算符oracle

> db.persons.find().limit(1).pretty()
{
        "_id" : ObjectId("5864d8d435ac4f57fb2528f8"),
        "name" : "robinson.cheng",
        "age" : 25,
        "email" : "robinson.cheng@qq.com",
        "score" : {
                "c" : 89,
                "m" : 96,
                "e" : 87
        },
        "country" : "USA",
        "books" : [
                "JS",
                "C++",
                "EXTJS",
                "MONGODB"
        ],
        "blog" : "http://blog.csdn.net/leshami"
}
> 
> //使用 \$set修改器修改age字段
> db.persons.update({name:"robinson.cheng"},{$set:{age:24}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> //使用$set修改器修改嵌套文檔,使用成員.方式來實現

> db.persons.update({name:"robinson.cheng"},{$set:{"score.c":92}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> //查看修改後的結果
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,age:1,score:1}).pretty()
{
        "name" : "robinson.cheng",
        "age" : 24,
        "score" : {
                "c" : 92,
                "m" : 96,
                "e" : 87
        }
}

二、將文檔普通字段轉換爲數組($set)url

//以下,將country設定爲數組
> db.persons.update({name:"robinson.cheng"},{$set:{country:["USA","CN","HK"]}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,country:1})
{ "name" : "robinson.cheng", "country" : [ "USA", "CN", "HK" ] }

三、文檔新增字段($set實現)spa

//下面使用$set文檔新增一個add字段,也可使用$inc實現新增字段(見後面的描述)
> db.persons.update({name:"robinson.cheng"},{$set:{add:"ShenZhen"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> //查看新增字段add
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,age:1,add:1})
{ "name" : "robinson.cheng", "age" : 24, "add" : "ShenZhen" }

四、文檔刪除字段.net

//注,字段的刪除方法爲{"$unset":{field_name:1}}

> db.persons.update({name:"robinson.cheng"},{"$unset":{add:1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//驗證刪除後的結果add未顯示
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,age:1,add:1})
{ "name" : "robinson.cheng", "age" : 24 }

五、字段值的增長或減小code

//當使用$inc修改器時,當字段不存在時,會自動建立該字段,若是存在,則在原有值的基礎上進行增長或者減小
//$inc主要是用於專門進行數字的增長或減小,所以$inc只能用於整型,長整形,或者雙精度浮點型的值
//$inc不支持字符串,數組以及其餘非數字的值
//注,對於$inc的操做,$set也能夠完成。$inc存在的理由是$inc更高效

//下面經過$inc新增salary字段
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:1000}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1}).pretty()
{ "name" : "robinson.cheng", "salary" : 1000 }

//再次執行$inc
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:2000}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//查詢結果爲在原有1000的基礎上增長2000,即爲3000
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1}).pretty()
{ "name" : "robinson.cheng", "salary" : 3000 }

//基於$inc的負值
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:-1500}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//負值後的結果
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1}).pretty()
{ "name" : "robinson.cheng", "salary" : 1500 }

//下面使用非數字來實現$inc,報錯以下
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:"1.5k"}})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 14,
                "errmsg" : "Cannot increment with non-numeric argument: {salary: \"1.5k\"}"
        }
})

六、時間戳字段的增長及自動更新($currentDate)

//有時候須要爲文檔增長最後的更新時間自動,可使用$currentDate方式來實現
//下面爲文檔增長lastModified時間戳字段
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:1000},$currentDate: {lastModified:true}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//查看結果
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1,lastModified:1})
{ "name" : "robinson.cheng", "salary" : 2500, "lastModified" : ISODate("2017-02-08T08:23:38.361Z") }

//再次更新
> db.persons.update({name:"robinson.cheng"},{$inc:{salary:500},$currentDate: {lastModified:true}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

//再次查看結果,時間戳自動被自動更新爲最新的時間
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1,lastModified:1})
{ "name" : "robinson.cheng", "salary" : 3000, "lastModified" : ISODate("2017-02-08T08:25:26.865Z")

七、文檔字段重命名($rename)

//下面使用$rename對文檔字段重命名
> db.persons.update({name:"robinson.cheng"},{$rename:{"name":"ename"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.persons.find({ename:"robinson.cheng"},{"_id":0,ename:1})
{ "ename" : "robinson.cheng" }

//對子文檔字段進行重命名
> db.persons.update({ename:"robinson.cheng"},{$rename:{"score.c":"score.chinese"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.persons.find({ename:"robinson.cheng"},{"_id":0,ename:1,score:1})
{ "score" : { "m" : 96, "e" : 87, "chinese" : 92 }, "ename" : "robinson.cheng" }

//對整個集合上全部文檔字段進行重命名
> db.persons.count()
12

> db.persons.update({},{$rename:{"name":"ename"}},{multi:true})
WriteResult({ "nMatched" : 12, "nUpserted" : 0, "nModified" : 11 }) //這次修改成11條,由於前面以及修改過1

3、upsert選項用法

// upsert至關於oracle的merge into或者mysql中的replace into // upsert便是當集合中匹配到知足條件的文檔時,則更新文檔,不然則是新增文檔。前提是該選項的值爲true,缺省爲flase。

> //下面的演示的是匹配到文檔時的例子
> db.persons.update({name:"robinson.cheng"},{$set:{salary:4000}},{upsert:true})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })  //此時提示有一個匹配,有一個被更新
> db.persons.find({name:"robinson.cheng"},{"_id":0,name:1,salary:1})
{ "name" : "robinson.cheng", "salary" : 4000 }

> //下面經過upsert方式來新增文檔
> db.persons.find({name:"thomas"})  //查找thomas
> db.persons.update({name:"thomas"},{$set:{salary:4000,country:"USA",age:25}},{upsert:true})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1, //此處結果表面有一個upserted,即沒有對應得文檔,更新的內容做爲一個新文檔插入到集合
        "nModified" : 0,
        "_id" : ObjectId("589ae6f4e3a46ff8c567f1bf")
})
> db.persons.find({name:"thomas"})
{ "_id" : ObjectId("589ae6f4e3a46ff8c567f1bf"), "name" : "thomas", "salary" : 4000, "country" : "USA", "age" : 25 }

4、小結

a、對於文檔上數據的修改有多種方式(修改器),經常使用的爲$set修改器以及$inc
b、$inc是一種高效的數據修改器,一般用於實現數值的增長或減小,僅支持數據類型。
c、對於文檔字段的增長,可使用$set,$unset,$inc,$currentDate等方式
d、對於文檔字段的刪除,使用$unset方式來實現 e、upsert選項能夠實現匹配的文檔則更新,不匹配時則插入

相關文章
相關標籤/搜索