MongoDB指南---五、建立、刪除文檔

上一篇文章: MongoDB指南---四、MongoDB基礎知識-使用MongoDB Shell
下一篇文章: MongoDB指南---六、更新文檔

本章會介紹對數據庫移入/移出數據的基本操做,具體包含以下操做:shell

  • 向集合添加新文檔;
  • 從集合裏刪除文檔;
  • 更新現有文檔;

爲這些操做選擇合適的安全級別和速度。數據庫

3.1 插入並保存文檔

插入是向MongoDB中添加數據的基本方法。可使用insert方法向目標集合插入一個文檔:segmentfault

> db.foo.insert({"bar" : "baz"})

這個操做會給文檔自動增長一個"_id"鍵(要是原來沒有的話),而後將其保存到MongoDB中。數組

3.1.1 批量插入

若是要向集合中插入多個文檔,使用批量插入會快一些。使用批量插入,能夠將一組文檔傳遞給數據庫。
在shell中,可使用batchInsert函數實現批量插入,它與insert函數很是像,只是它接受的是一個文檔數組做爲參數:安全

> db.foo.batchInsert([{"_id" : 0}, {"_id" : 1}, {"_id" : 2}])
> db.foo.find()
{ "_id" : 0 }
{ "_id" : 1 }
{ "_id" : 2 }

一次發送數10、數百乃至數千個文檔會明顯提升插入的速度。
只有須要將多個文檔插入到一個集合時,這種方式纔會有用。不能在單次請求中將多個文檔批量插入到多個集合中。要是隻導入原始數據(例如,從數據feed或者MySQL中導入),可使用命令行工具,如mongoimport,而不是批量插入。另外一方面,可使用批量插入在將數據存入MongoDB以前對數據作一些小的修整(將日期轉換爲日期類型,或添加自定義的"_id"),這樣批量插入也可用於導入數據。
當前版本的MongoDB能接受的最大消息長度是48 MB,因此在一次批量插入中能插入的文檔是有限制的。若是試圖插入48 MB以上的數據,多數驅動程序會將這個批量插入請求拆分爲多個48 MB的批量插入請求。具體能夠查看所使用的驅動程序的相關文檔。
若是在執行批量插入的過程當中有一個文檔插入失敗,那麼在這個文檔以前的全部文檔都會成功插入到集合中,而這個文檔以及以後的全部文檔所有插入失敗。服務器

> db.foo.batchInsert([{"_id" : 0}, {"_id" : 1}, {"_id" : 1}, {"_id" : 2}])

只有前兩個文檔會被插入,由於插入第三個文檔時會發生錯誤:集合中已經存在一個_id爲1的文檔,不能重複插入。
在批量插入中遇到錯誤時,若是但願batchInsert忽略錯誤而且繼續執行後續插入,可使用continueOnError選項。這樣就能夠將上面例子中的第一個、第二個以及第四個文檔都插入到集合中。Shell並不支持這個選項,可是全部驅動程序都支持。函數

3.1.2 插入校驗

插入數據時,MongoDB只對數據進行最基本的檢查:檢查文檔的基本結構,若是沒有"_id"字段,就自動增長一個。檢查大小就是其中一項基本結構檢查:全部文檔都必須小於16 MB(這個值是MongoDB設計者人爲定的,將來有可能會增長)。做這樣的限制主要是爲了防止不良的模式設計,而且保證性能一致。若是要查看doc文檔的BSON大小(單位爲字節),能夠在shell中執行Object.bsonsize(doc)。
16 MB的數據究竟有多大?要知道整部《戰爭與和平》也才3.14 MB。
因爲MongoDB只進行最基本的檢查,因此插入非法數據很容易(若是你想這麼幹的話)。所以,應該只容許信任的源(好比你的應用程序服務器)鏈接數據庫。主流語言的全部驅動程序(以及大部分其餘語言的驅動程序),都會在將數據插入到數據庫以前作大量的數據校驗(好比文檔是否過大,文檔是否包含非UTF-8字符串,是否使用不可識別的類型)。工具

3.2 刪除文檔

如今數據庫中有些數據,要刪除它:性能

> db.foo.remove()

上述命令會刪除foo集合中的全部文檔。可是不會刪除集合自己,也不會刪除集合的元信息。
remove函數能夠接受一個查詢文檔做爲可選參數。給定這個參數之後,只有符合條件的文檔才被刪除。例如,假設要刪除mailing.list集合中全部"opt-out"爲true的人:測試

> db.mailing.list.remove({"opt-out" : true})

刪除數據是永久性的,不能撤銷,也不能恢復。

刪除速度

刪除文檔一般很快,可是若是要清空整個集合,那麼使用drop直接刪除集合會更快(而後在這個空集合上重建各項索引)。
例如,使用以下方法插入一百萬個測試數據:

> for (var i = 0; i < 1000000; i++) {
     db.tester.insert({"foo": "bar", "baz": i, "z": 10 - i})
 }

如今把剛插入的文檔都刪除,並記錄花費的時間。首先使用remove進行刪除:

> var timeRemoves = function() {
... var start = (new Date()).getTime();
...
... db.tester.remove();
... db.findOne(); // makes sure the remove finishes before continuing
...
... var timeDiff = (new Date()).getTime() - start;
... print("Remove took: "+timeDiff+"ms");
... }
> timeRemoves()

在MacBookAir筆記本電腦上,這段腳本輸出「Removetook:9676ms」。
若是用db.tester.drop()代替remove和findOne,只用1 ms!速度提高至關明顯,但也是有代價的:不能指定任何限定條件。整個集合都被刪除了,全部元數據也都不見了。

上一篇文章: MongoDB指南---四、MongoDB基礎知識-使用MongoDB Shell
下一篇文章: MongoDB指南---六、更新文檔
相關文章
相關標籤/搜索