1. 程式人生 > >4.mongoDB shell 之增刪改操作

4.mongoDB shell 之增刪改操作

4.1 insert增加操作

1.向給定資料庫新增集合並且新增記錄

db.[documentName].insert({…})

插入資料時需注意事項:

  • 1.1 每條資料都有一個_id欄位,如果不指定,則使用ObjectId型別的隨機值作為id。
    ObjectId由12個位元組組成,【時間戳,精確到秒–4位元組】【機器標識–3位元組】
    【程序id–2位元組】【隨機計數器–3位元組】

  • 1.2 _id 欄位唯一,不能重複插入

2.save操作和insert操作的區別:

  • 在遇到相同的_id情況下,save操作會對當前內容進行覆蓋儲存,而insert操作無法插入,報錯主鍵重複

4.2 remove移除操作

1.刪除文件中的資料

db.[documentName].remove({...})

2. 刪除列表中所有的資料

db.persons.remove()

例子:刪除集合person中name等於uspcat的記錄

db.persons.remove({name:"uspcat"})
> db.persons.find();
{ "_id" : ObjectId("57fdebdacf77bc67373cbb8e"), "name" : "extjs4.1" }
{ "_id" : ObjectId("57fdb688cf77bc67373cbb8d"
), "age" : 1, "name" : "uspcat4" } > db.persons.remove({name:"extjs4.1"}) > db.persons.find(); { "_id" : ObjectId("57fdb688cf77bc67373cbb8d"), "age" : 1, "name" : "uspcat4" }

小技巧
如果你想清除一個數據量十分龐大的集合,直接刪除(db.persons.drop)該集合並且重新建立索引的辦法比直接用remove的效率高很多

4.3 update更新操作詳解

更新文件資料

db.[documentName]
.update({查詢條件},{更新內容},<upsert>,<multi>)

(boolean)upsert: 預設為false。如果設定為true,表示如果沒有找到匹配選項則建立新的文件內容進行插入
(boolean)multi: 預設情況下,只更新匹配條件下的第一個匹配文件,如果設定為true,則更新所有匹配的文件,其他欄位不變
更新器沒有$set的情況:將更新內容賦給查詢器匹配的文件,除主鍵外,更新內容不包含的欄位一律清除

1 強硬的文件替換式更新操作

語法:

db.[documentName].update({查詢器},{修改器})

舉例:

> db.text.find()
{ "_id" : ObjectId("58286ed97bd74a5a3114faca"), "name" : 
"yfc", "age" : 27 }

將name為‘yfc’的人的age改為29
> db.text.update({name:"yfc"},{age:29})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

發現欄位中name不見了,只剩下age欄位為29
> db.text.find()
{ "_id" : ObjectId("58286ed97bd74a5a3114faca"), "age" : 29 }

注:強硬的更新會將老文件用新文件代替,通常開發中很少使用這種方法

2 主鍵衝突的時候會報錯並且停止更新操作

3 insertOrUpdate操作(多一個引數)
  目的:查詢器查出來資料就執行更新操作,查不出來就執行插入操作
  做法db.[documentName].update({查詢器},{修改器},true)

> db.text.find()
{ "_id" : ObjectId("58286ed97bd74a5a3114faca"), "age" : 29 }
{ "_id" : 1, "name" : "name1", "age" : "age1" }
{ "_id" : 2, "name" : "name2", "age" : "age2" }
{ "_id" : 3, "age" : 40 }
{ "_id" : ObjectId("58287308c60186988c96cc68"), "age" : 41 }

想要更新name=”name5”的文件,但是找不到,則進行插入操作

> db.text.update({name:"name5"},{"_id":5,age:50},true)
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 5 })
> db.text.find()    發現新增了一行
{ "_id" : ObjectId("58286ed97bd74a5a3114faca"), "age" : 29 }
{ "_id" : 1, "name" : "name1", "age" : "age1" }
{ "_id" : 2, "name" : "name2", "age" : "age2" }
{ "_id" : 3, "age" : 40 }
{ "_id" : ObjectId("58287308c60186988c96cc68"), "age" : 41 }
{ "_id" : 5, "age" : 50 }

4 批量更新操作(增加引數3,4)
  目的:對查詢器查出來多個匹配結進行更新操作
  做法:db.[documentName].update({查詢器},{修改器},false,true)
使用普通更新操作無法完成需求:

> db.text.find()
{ "_id" : "1", "name" : "tom1", "age" : 21 }
{ "_id" : "2", "name" : "tom2", "age" : 21 }
{ "_id" : "3", "name" : "tom3", "age" : 33 }

想要改變所有年齡為21的為22

> db.text.update({"age":21},{$set:{age:22}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

發現只是更新了第一個匹配結果

> db.text.find() 
{ "_id" : "1", "name" : "tom1", "age" : 22 }
{ "_id" : "2", "name" : "tom2", "age" : 21 }
{ "_id" : "3", "name" : "tom3", "age" : 33 }

使用批量更新操作重新試試看
增加 引數3:false(不進行insertOrUpdate操作)
   引數4:true(對所有匹配的內容進行批量修改)

> db.text.update({"age":21},{$set:{age:22}},false,true)
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })

發現所有匹配到的結果都進行了更新操作

> db.text.find() 
{ "_id" : "1", "name" : "tom1", "age" : 22 }
{ "_id" : "2", "name" : "tom2", "age" : 22 }
{ "_id" : "3", "name" : "tom3", "age" : 33 }

5.使用修改器來完成區域性更新的操作

修改器名稱 語法 案例
$set {$set:{field:value}} {$set:{ gender: "male"}}

指定一個鍵值對,如果存在該鍵就進行修改,如果不存在則進行新增
update之前

> db.text.find() 
{ "_id" : "1", "name" : "tom1", "age" : 22 }
{ "_id" : "2", "name" : "tom2", "age" : 22 }
{ "_id" : "3", "name" : "tom3", "age" : 33 }

將姓名為 tom3 的人的性別 gender 改為 male :
update之後,發現多了一個gender鍵

> db.text.update({"name":"tom3"},{$set:{gender:"male"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.text.find()
{ "_id" : "1", "name" : "tom1", "age" : 22 }
{ "_id" : "2", "name" : "tom2", "age" : 22 }
{ "_id" : "3", "name" : "tom3", "age" : 33, "gender" : "male" }
修改器名稱 語法 案例
$inc {$inc:{field:value}} {$inc:{"age":1}}

操作物件必須是數字型別,可以為指定的鍵對應的數字型別的數值進行加減操作(正數為加,負數為減)

> db.user.find()
{ "_id" : 1, "name" : "user1", "age" : 21 }
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }

給user1年齡加3
> db.user.update({"name":"user1"},{$inc:{"age":3}}) 
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

發現user1的年齡增加了3歲
> db.user.find() 
{ "_id" : 1, "name" : "user1", "age" : 24 }
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
修改器名稱 語法 案例
$unset {$unset:{field:1}} {$unset:{}}

移除指定的鍵:

移除age鍵

> db.user.update({"name":"user1"},{$unset:{"age":1}}) 
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

發現user1的age鍵不見了
> db.user.find() 
{ "_id" : 1, "name" : "user1" }
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
修改器名稱 語法 案例
$push {$push:{field:value}} {$push:{books:"JS"}}

(該修改器只針對陣列有效
1.如果指定的鍵是陣列則追加新的數值
2.如果不存在指定的鍵則建立陣列型別的鍵值對

> db.user.update({"name":"user1"},{$push:{"age":1}})
> db.user.update({"name":"user1"},{$push:{"age":2}})
> db.user.update({"name":"user1"},{$push:{"age":1}})


 看到增加了陣列型別的age鍵值對
> db.user.find() 
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 1, 2, 1 ] }
修改器名稱 語法 案例
$pushAll {$pushAll:{field:array}}} {$pushAll:{books:["JS","java"]}}

批量對陣列新增資料,如果不存在則建立
(該修改器只針對陣列有效

> db.user.update({"name":"user1"},{$pushAll:{"books":["java","python","scala"]}})
> db.user.find()
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 1, 2, 1, 3, 4, 5, 4 ], "books" : [ "java", "python", "scala" ] }
修改器名稱 語法 案例
$addToSet {$addToSet:{field:value}} {$pushAll:{books:"JS"}}

對陣列新增資料,對於存在的資料不加入,如果不存在則加入
(該修改器只針對陣列有效

原始資料:
> db.user.find()
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 1, 2, 1, 3, 4, 5, 4 ], "books" : [ "java", "python", "scala" ] }


> db.user.update({"name":"user1"},{$addToSet:{"books":"java"}})
沒有寫成功,因為java已經存在於陣列中了

> db.user.update({"name":"user1"},{$addToSet:{"books":"javaWeb"}})

寫成功了,java因為存在所以不寫入,javaWeb因為不存在所以寫入了:
> db.user.find()
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 1, 2, 1, 3, 4, 5, 4 ], "books" : [ "java", "python", "scala", "javaWeb" ] }
修改器名稱 語法 案例
$pop {$pop:{field:value}}} {$pop:{books:1}}

從指定陣列刪除首/尾的值。-1:刪除首部值 1:刪除尾部值
(該修改器只針對陣列有效

原始資料:
> db.user.find()
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 1, 2, 1, 3, 4, 5, 4 ], "books" : [ "java", "python", "scala", "javaWeb" ] }

刪除 user1 的 books 陣列中第一個元素
> db.user.update({"name":"user1"},{$pop:{"books":-1}}) 

發現 book 陣列中的 java 不見了
> db.user.find()  
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 1, 2, 1, 3, 4, 5, 4 ], "books" : [ "python", "scala", "javaWeb" ] }
修改器名稱 語法 案例
$pull {$pull:{field:value}} {$pull:{"age":1}}

刪除陣列中指定的數值
(該修改器只針對陣列有效

原始資料:
> db.user.find()
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 1, 2, 1, 3, 4 ], "books" : [ "python", "scala", "javaWeb" ], "gender" : "male" }

刪除age陣列中所有的1
> db.user.update({"name":"user1"},{$pull:{"age":1}},false,true) 

發現age陣列中已經沒有了1
> db.user.find() 
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 2, 3, 4 ], "books" : [ "python", "scala", "javaWeb" ], "gender" : "male" }
修改器名稱 語法 案例
$pullAll {$pullAll:{field:value}} {$pullAll:{books:"javaWeb"}}

一次性刪除多個指定的數值
(該修改器只針對陣列有效

{ "_id" : 1, "name" : "user1", "age" : [ 2, 3, 4 ], "books" : [ "python", "scala", "javaWeb" ], "gender" : "male" }

批量刪除 user1 的 books屬性中的"python","javaWeb"
> db.user.update({"name":"user1"},{$pullAll:{"books":["python","javaWeb"]}})

"python","javaWeb"已經被刪掉了
> db.user.find()
{ "_id" : 2, "name" : "user2", "age" : 22 }
{ "_id" : 3, "name" : "user3", "age" : 23 }
{ "_id" : 1, "name" : "user1", "age" : [ 2, 3, 4 ], "books" : [ "scala" ], "gender" : "male"}

其他型別

1.陣列定位器

如果陣列有多個值我們只想對其中一部分進行操作,就要用到定位器

例子:
例如有文件

{"_id":"4",
"desc":
[{"name":"js","type":"avi"},
{"name":"hadoop","type":"rmvb"},
{"name":"spark","type":"mp4"}]}

我們要向desc陣列中type等於”avi”的文件增加一個相同的作者author是”llj”

注:切記修改器是放到最外面,後面要學的查詢器是放到內層的

2.$add$each 結合完成批量陣列更新

對文件:{ “_id” : 1, “books” : [ “js”, “scala” ] }中的內容進行修改
向books陣列插入”js”、”python”兩個值,要求做重複性檢查

> db.user.update({"_id":1},{$addToSet:{books:{$each:["js","python"]}}})

發現update執行後,只對”python”進行了更新,而”js”沒有插入

> db.user.find()  
…
{ "_id" : 1, "books" : [ "js", "scala", "python" ] }

3.存在分配與查詢效率

當document被建立的時候DB為其分配記憶體和預留記憶體,當修改操作不超過預留記憶體的時候,則速度非常快,反之,超過了預留記憶體則會消耗時間

4.runCommand函式和findAndModify函式

runCommand可以執行mongoDB中的特殊函式
findAndModify就是特殊函式之一,它的作用是返回update或remove後的文件
格式:

runCommand({"findAndModify":"文件名稱",
            query:{查詢器},
            sort{排序},
            new:true,
            update:{更新器},
            remove:true
}).value

舉例:
更新文件{ "_id" : 3, "name" : "user3", "age" : 23 },將其中的age改為88

> ps = db.runCommand({
findAndModify:"user",
query:{_id:3},
update:{$set:{age:88}},
new:true
})
> ps.value
{ "_id" : 3, "name" : "user3", "age" : 88 }