MongoDB最基礎的部分已經看的差不多了,作為數據庫來說做的最多的還是對數據庫數據的操作。本文將介紹MongoDB中一下三點
- 向集合中添加新文檔
- 從集合中刪除文檔
- 更新現有文檔
插入並保存文檔
插入一條記錄
> db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password " : "121212", "tel" : "121212" } > db.user.insert({username:'aaa',password:'bbb',tel:'123123123'}); > db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password " : "121212", "tel" : "121212" } { "_id" : ObjectId("51b91edc32b7955cd61dbc8e"), "username" : "aaa", "password" : "bbb", "tel" : "123123123" } >
操作為文檔增加了一個“_id”,然后保存到了MongoDB中
> db.user.insert({_id:'12345678',username:'aaa',password:'bbb',tel:'123123123'}) ; > db.user.find(); { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password " : "121212", "tel" : "121212" } { "_id" : ObjectId("51b91edc32b7955cd61dbc8e"), "username" : "aaa", "password" : "bbb", "tel" : "123123123" } { "_id" : "12345678", "username" : "aaa", "password" : "bbb", "tel" : "123123123 " } >
如果我們自己定義了一個_id的話,數據庫就不在自己生存,可以看到數據庫自己生成的是ObjectId。
批量插入
如果要插入多個文檔,批量要快一些。批量插入能傳遞一個由文檔構成的數組給數據庫
一次發送多個文檔會提高插入數度。一次插入需要建立一個TCP鏈接。批量提交,會比多次提交數據少建立TCP連接,避免了零碎的請求開銷。而且批量提交只會有一個文件頭信息,數據不用多次的處理文件頭。
用數組的方式一次插入兩條數據
> db.user.insert([{username:'aaa',password:'bbb',tel:'123123123'},{username:'bbb ',password:'ccc',tel:'123123234'}]); > db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password " : "121212", "tel" : "121212" } { "_id" : ObjectId("51b91edc32b7955cd61dbc8e"), "username" : "aaa", "password" : "bbb", "tel" : "123123123" } { "_id" : "12345678", "username" : "aaa", "password" : "bbb", "tel" : "123123123 " } { "_id" : ObjectId("51b920ca32b7955cd61dbc8f"), "username" : "aaa", "password" : "bbb", "tel" : "123123123" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "username" : "bbb", "password" : "ccc", "tel" : "123123234" } >
插入原理和作用
當執行插入事,使用的驅動會將數據轉換為BSON的形式,將其送入數據庫。數據庫解析BSON,檢驗是否有_id,和文檔的大小,除此之外,文檔不做別的數據驗證,簡單的將數據存入數據庫中。
ps.大於4M的文檔是不能存入數據庫中的。
刪除文檔
刪除文檔用
> db.user.remove()
如果remove不傳入任何參數,會刪除所有文檔,但不會刪除集合本身,原索引也會保留。
如果給定參數,只有符合條件的才會刪除
> db.user.remove({username:'aaa'}) > db.user.find(); { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password " : "121212", "tel" : "121212" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "username" : "bbb", "password" : "ccc", "tel" : "123123234" } >
刪除速度
刪除文檔通常會很快,但是要清除整個集合,直接刪除集合會更快
更新文檔
文檔存入數據庫后,就可以用update方法來修改它,update有兩個參數一個是查詢文檔,找出需要更新的文檔。一個是修改文檔,描述對找到的文檔做哪些修改
更新操作是原子的,若是兩個更新同時發生,先到達服務器的先執行。
文檔替換
更新最簡單的就是完全用一個新文檔替代匹配文檔。比如我們將username為bb的文檔替換為如下
> db.user.update({username:'bbb'},{password:'abc'}); > db.user.find(); { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password " : "121212", "tel" : "121212" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } >
我們發現文檔結構被替換成了
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } >
也就是說這樣的替換是直接替換文檔,而不是做修改。在大的改動的情況下,使用文檔變更可以直接替換文檔,但有時候這樣卻不是我們想要的,我們只是希望修改password而不變動其他的內容
使用修改器
通常文檔只會有部分要更新。利用原子的修改器,可以用來部分更新。
$set修改器
$set用來指定一個鍵的值,如果這個鍵不存在,就創建它。下面我們修改username為wangwu的password的值
> db.user.find(); { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password " : "121212", "tel" : "121212" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } > db.user.update({username:'wangwu'},{$set:{password:'abcdef'}}); > db.user.find(); { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password " : "abcdef", "tel" : "121212" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } >
$unset修改器
$unset來刪除一個鍵,比如刪除username為wangwu的tel鍵
> db.user.update({username:'wangwu'},{$unset:{tel:1}}); > db.user.find(); { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "password" : "abcdef", "username " : "wangwu" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } >
$inc修改器
$inc用來增加已有的鍵值,或者在鍵值不存在時創建。
現在我們需要一個age的值
現在給age執行$inc
> db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "password" : "abcdef", "username " : "wangwu" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } > db.user.update({username:'wangwu'},{$inc:{age:1}}); > db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 1, "password" : "abcdef" , "username" : "wangwu" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } > db.user.update({username:'wangwu'},{$inc:{age:1}}); > db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "password" : "abcdef" , "username" : "wangwu" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } >
這里執行了兩次$inc,age第一次創建了一個值為1的鍵值,然后自加了1.
$inc鍵的值必須為數字,如果嘗試修改成其他類型就會出現如下錯誤
> db.user.update({username:'wangwu'},{$inc:{age:'abc'}});
Modifier $inc allowed for numbers only
>
數組修改器
數組修改器只能用於數組。
$push會像已有的數組末尾假如一個元素
$pop會從頭部刪除一個元素
> db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "password" : "abcdef" , "username" : "wangwu" } { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } > db.user.update({username:'wangwu'},{$push:{arr:1}}); > db.user.find() { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ 1 ], "pass word" : "abcdef", "username" : "wangwu" } > db.user.update({username:'wangwu'},{$push:{arr:2}}); > db.user.find() { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ 1, 2 ], " password" : "abcdef", "username" : "wangwu" } > db.user.update({username:'wangwu'},{$pop:{arr:2}}); > db.user.find() { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ 1 ], "pass word" : "abcdef", "username" : "wangwu" } > db.user.update({username:'wangwu'},{$pop:{arr:2}}); > db.user.find() { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ ], "passwor d" : "abcdef", "username" : "wangwu" }
數組的定位修改器
若是數組中多個值,我們只想修改其中的部分值,有兩種方法操作數組中的值:通過位置和定位操作符($)
> db.user.update({username:'wangwu'},{$set:{'arr.1':1}}); > db.user.find() { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ 2, 1, 3, 4 ], "password" : "a", "username" : "wangwu" } > db.user.update({username:'wangwu'},{$set:{'arr.$':1}}); Cannot apply the positional operator without a corresponding query field contain ing an array. > db.user.update({'arr.1':1},{$set:{'arr.$':1}}); > db.user.update({'arr.1':1},{$set:{'arr.$':3}}); > db.user.find() { "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" } { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ 2, 3, 3, 4 ], "password" : "a", "username" : "wangwu" } >
使用位置可以直接修改指定位置的數據,使用定位操作符是在查詢的時候不知道該位置的時候使用,這個時候需要注意的是查詢username的時候,使用$會報出錯誤。也就是查詢出來的值不是數組,所以不能用$來指定
upsert
upsert是一個特殊的更新。當沒有文檔符合更新條件,就會以這個條件創建新的文檔。當update的第三個參數設置為true的時候,為upsert模式
> db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ 2, 3, 3, 4 ], "password" : "a", "username" : "wangwu" } > db.user.update({age:1},{$set:{abc:123}},true) > db.user.find() { "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ 2, 3, 3, 4 ], "password" : "a", "username" : "wangwu" } { "_id" : ObjectId("51ba745f5fdf5d2d7426eb35"), "abc" : 123, "age" : 1 } >
更新多個文檔
默認情況下,更新只能對符合匹配條件的第一個文檔操作,要是有多個文檔符合條件,其余的文檔就沒有變化。要使所有的文檔都得到更新,可以設置update的第四個參數為true
返回已經更新的文檔
用getLastError只能獲取有限的信息,並不能返回更新的文檔。這個可以通過findAndModify來做到。
安全操作
MongoDB選中選擇不安全的版本作為默認操作,如果需要判斷狀態,在執行完操作后立即運行getLastError,來檢查是否成功。
如果不考慮安全性的問題,就無序調用getLastError
把重要的數據用安全的方式操作
請求和連接
數據庫為MongoDB創建了一個隊列,存放這個連接請求。當客戶端發送一個請求,會被放到隊列的末尾。只有隊列中的請求都執行完畢,后續的請求才會執行。每個連接都有獨立的隊列。