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 }