MongoDB 的關係表示多個文檔之間在邏輯上的相互聯繫。php
文檔間能夠經過嵌入和引用來創建聯繫。正則表達式
MongoDB 中的關係能夠是:mongodb
接下來咱們來考慮下用戶與用戶地址的關係。數據庫
一個用戶能夠有多個地址,因此是一對多的關係。編程
如下是 user 文檔的簡單結構:數組
{ "_id":ObjectId("52ffc33cd85242f436000001"), "name": "Tom Hanks", "contact": "987654321", "dob": "01-01-1991" }
如下是 address 文檔的簡單結構:瀏覽器
{ "_id":ObjectId("52ffc4a5d85242602e000000"), "building": "22 A, Indiana Apt", "pincode": 123456, "city": "Los Angeles", "state": "California" }
使用嵌入式方法,咱們能夠把用戶地址嵌入到用戶的文檔中:緩存
"_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address": [ { "building": "22 A, Indiana Apt", "pincode": 123456, "city": "Los Angeles", "state": "California" }, { "building": "170 A, Acropolis Apt", "pincode": 456789, "city": "Chicago", "state": "Illinois" }] }
以上數據保存在單一的文檔中,能夠比較容易的獲取和維護數據。 你能夠這樣查詢用戶的地址:安全
>db.users.findOne({"name":"Tom Benzamin"},{"address":1})
注意:以上查詢中 db 和 users 表示數據庫和集合。服務器
這種數據結構的缺點是,若是用戶和用戶地址在不斷增長,數據量不斷變大,會影響讀寫性能。
引用式關係是設計數據庫時常常用到的方法,這種方法把用戶數據文檔和用戶地址數據文檔分開,經過引用文檔的 id 字段來創建關係。
{ "_id":ObjectId("52ffc33cd85242f436000001"), "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin", "address_ids": [ ObjectId("52ffc4a5d85242602e000000"), ObjectId("52ffc4a5d85242602e000001") ] }
以上實例中,用戶文檔的 address_ids 字段包含用戶地址的對象id(ObjectId)數組。
咱們能夠讀取這些用戶地址的對象id(ObjectId)來獲取用戶的詳細地址信息。
這種方法須要兩次查詢,第一次查詢用戶地址的對象id(ObjectId),第二次經過查詢的id獲取用戶的詳細地址信息。
>var result = db.users.findOne({"name":"Tom Benzamin"},{"address_ids":1}) >var addresses = db.address.find({"_id":{"$in":result["address_ids"]}})
在上一章節MongoDB關係中咱們提到了MongoDB的引用來規範數據結構文檔。
MongoDB 引用有兩種:
考慮這樣的一個場景,咱們在不一樣的集合中 (address_home, address_office, address_mailing, 等)存儲不一樣的地址(住址,辦公室地址,郵件地址等)。
這樣,咱們在調用不一樣地址時,也須要指定集合,一個文檔從多個集合引用文檔,咱們應該使用 DBRefs。
DBRef的形式:
{ $ref : , $id : , $db : }
三個字段表示的意義爲:
如下實例中用戶數據文檔使用了 DBRef, 字段 address:
{ "_id":ObjectId("53402597d852426020000002"), "address": { "$ref": "address_home", "$id": ObjectId("534009e4d852427820000002"), "$db": "w3cschoolcc"}, "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin" }
address DBRef 字段指定了引用的地址文檔是在 address_home 集合下的 w3cschoolcc 數據庫,id 爲 534009e4d852427820000002。
如下代碼中,咱們經過指定 $ref 參數(address_home 集合)來查找集合中指定id的用戶地址信息:
>var user = db.users.findOne({"name":"Tom Benzamin"}) >var dbRef = user.address >db[dbRef.$ref].findOne({"_id":(dbRef.$id)})
以上實例返回了 address_home 集合中的地址數據:
{ "_id" : ObjectId("534009e4d852427820000002"), "building" : "22 A, Indiana Apt", "pincode" : 123456, "city" : "Los Angeles", "state" : "California" }
官方的MongoDB的文檔中說明,覆蓋查詢是如下的查詢:
因爲全部出如今查詢中的字段是索引的一部分, MongoDB 無需在整個數據文檔中檢索匹配查詢條件和返回使用相同索引的查詢結果。
由於索引存在於RAM中,從索引中獲取數據比經過掃描文檔讀取數據要快得多。
爲了測試蓋索引查詢,使用如下 users 集合:
{ "_id": ObjectId("53402597d852426020000002"), "contact": "987654321", "dob": "01-01-1991", "gender": "M", "name": "Tom Benzamin", "user_name": "tombenzamin" }
咱們在 users 集合中建立聯合索引,字段爲 gender 和 user_name :
>db.users.ensureIndex({gender:1,user_name:1})
如今,該索引會覆蓋如下查詢:
>db.users.find({gender:"M"},{user_name:1,_id:0})
也就是說,對於上述查詢,MongoDB的不會去數據庫文件中查找。相反,它會從索引中提取數據,這是很是快速的數據查詢。
因爲咱們的索引中不包括 _id 字段,_id在查詢中會默認返回,咱們能夠在MongoDB的查詢結果集中排除它。
下面的實例沒有排除_id,查詢就不會被覆蓋:
>db.users.find({gender:"M"},{user_name:1})
最後,若是是如下的查詢,不能使用覆蓋索引查詢:
MongoDB 查詢分析能夠確保咱們建議的索引是否有效,是查詢語句性能分析的重要工具。
MongoDB 查詢分析經常使用函數有:explain() 和 hint()。
explain 操做提供了查詢信息,使用索引及查詢統計等。有利於咱們對索引的優化。
接下來咱們在 users 集合中建立 gender 和 user_name 的索引:
>db.users.ensureIndex({gender:1,user_name:1}) </p> <p>如今在查詢語句中使用 explain :</p> <pre> >db.users.find({gender:"M"},{user_name:1,_id:0}).explain()
以上的 explain() 查詢返回以下結果:
{ "cursor" : "BtreeCursor gender_1_user_name_1", "isMultiKey" : false, "n" : 1, "nscannedObjects" : 0, "nscanned" : 1, "nscannedObjectsAllPlans" : 0, "nscannedAllPlans" : 1, "scanAndOrder" : false, "indexOnly" : true, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { "gender" : [ [ "M", "M" ] ], "user_name" : [ [ { "$minElement" : 1 }, { "$maxElement" : 1 } ] ] } }
如今,咱們看看這個結果集的字段:
雖然MongoDB查詢優化器通常工做的很不錯,可是也可使用 hint 來強制 MongoDB 使用一個指定的索引。
這種方法某些情形下會提高性能。 一個有索引的 collection 而且執行一個多字段的查詢(一些字段已經索引了)。
以下查詢實例指定了使用 gender 和 user_name 索引字段來查詢:
>db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1})
可使用 explain() 函數來分析以上查詢:
>db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain()
mongodb不支持事務,因此,在你的項目中應用時,要注意這點。不管什麼設計,都不要要求mongodb保證數據的完整性。
可是mongodb提供了許多原子操做,好比文檔的保存,修改,刪除等,都是原子操做。
所謂原子操做就是要麼這個文檔保存到Mongodb,要麼沒有保存到Mongodb,不會出現查詢到的文檔沒有保存完整的狀況。
考慮下面的例子,圖書館的書籍及結帳信息。
實例說明了在一個相同的文檔中如何確保嵌入字段關聯原子操做(update:更新)的字段是同步的。
book = { _id: 123456789, title: "MongoDB: The Definitive Guide", author: [ "Kristina Chodorow", "Mike Dirolf" ], published_date: ISODate("2010-09-24"), pages: 216, language: "English", publisher_id: "oreilly", available: 3, checkout: [ { by: "joe", date: ISODate("2012-10-15") } ] }
你可使用 db.collection.findAndModify() 方法來判斷書籍是否可結算並更新新的結算信息。
在同一個文檔中嵌入的 available 和 checkout 字段來確保這些字段是同步更新的:
db.books.findAndModify ( { query: { _id: 123456789, available: { $gt: 0 } }, update: { $inc: { available: -1 }, $push: { checkout: { by: "abc", date: new Date() } } } } )
用來指定一個鍵並更新鍵值,若鍵不存在並建立。
{ $set : { field : value } }
用來刪除一個鍵。
{ $unset : { field : 1} }
$inc能夠對文檔的某個值爲數字型(只能爲知足要求的數字)的鍵進行增減的操做。
{ $inc : { field : value } }
用法:
{ $push : { field : value } }
把value追加到field裏面去,field必定要是數組類型才行,若是field不存在,會新增一個數組類型加進去。
同$push,只是一次能夠追加多個值到一個數組字段內。
{ $pushAll : { field : value_array } }
從數組field內刪除一個等於value值。
{ $pull : { field : _value } }
增長一個值到數組內,並且只有當這個值不在數組內才增長。
刪除數組的第一個或最後一個元素
{ $pop : { field : 1 } }
修改字段名稱
{ $rename : { old_field_name : new_field_name } }
位操做,integer類型
{$bit : { field : {and : 5}}}
> t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 3 }, { "by" : "jane", "votes" : 7 } ] } > t.update( {'comments.by':'joe'}, {$inc:{'comments.$.votes':1}}, false, true ) > t.find() { "_id" : ObjectId("4b97e62bf1d8c7152c9ccb74"), "title" : "ABC", "comments" : [ { "by" : "joe", "votes" : 4 }, { "by" : "jane", "votes" : 7 } ] }
考慮如下文檔集合(users ):
{ "address": { "city": "Los Angeles", "state": "California", "pincode": "123" }, "tags": [ "music", "cricket", "blogs" ], "name": "Tom Benzamin" }
以上文檔包含了 address 子文檔和 tags 數組。
假設咱們基於標籤來檢索用戶,爲此咱們須要對集合中的數組 tags 創建索引。
在數組中建立索引,須要對數組中的每一個字段依次創建索引。因此在咱們爲數組 tags 建立索引時,會爲 music、cricket、blogs三個值創建單獨的索引。
使用如下命令建立數組索引:
>db.users.ensureIndex({"tags":1})
建立索引後,咱們能夠這樣檢索集合的 tags 字段:
>db.users.find({tags:"cricket"})
爲了驗證咱們使用使用了索引,可使用 explain 命令:
>db.users.find({tags:"cricket"}).explain()
以上命令執行結果中會顯示 "cursor" : "BtreeCursor tags_1" ,則表示已經使用了索引。
假設咱們須要經過city、state、pincode字段來檢索文檔,因爲這些字段是子文檔的字段,因此咱們須要對子文檔創建索引。
爲子文檔的三個字段建立索引,命令以下:
>db.users.ensureIndex({"address.city":1,"address.state":1,"address.pincode":1})
一旦建立索引,咱們可使用子文檔的字段來檢索數據:
>db.users.find({"address.city":"Los Angeles"})
記住查詢表達式必須遵循指定的索引的順序。因此上面建立的索引將支持如下查詢:
>db.users.find({"address.city":"Los Angeles","address.state":"California"})
一樣支持如下查詢:
>db.users.find({"address.city":"LosAngeles","address.state":"California","address.pincode":"123"})
每一個索引佔據必定的存儲空間,在進行插入,更新和刪除操做時也須要對索引進行操做。因此,若是你不多對集合進行讀取操做,建議不使用索引。
因爲索引是存儲在內存(RAM)中,你應該確保該索引的大小不超過內存的限制。
若是索引的大小大於內存的限制,MongoDB會刪除一些索引,這將致使性能降低。
索引不能被如下的查詢使用:
因此,檢測你的語句是否使用索引是一個好的習慣,能夠用explain來查看。
從2.6版本開始,若是現有的索引字段的值超過索引鍵的限制,MongoDB中不會建立索引。
若是文檔的索引字段值超過了索引鍵的限制,MongoDB不會將任何文檔轉換成索引的集合。與mongorestore和mongoimport工具相似。
在前面幾個章節中咱們已經使用了MongoDB 的對象 Id(ObjectId)。
在本章節中,咱們將瞭解的ObjectId的結構。
ObjectId 是一個12字節 BSON 類型數據,有如下格式:
MongoDB中存儲的文檔必須有一個"_id"鍵。這個鍵的值能夠是任何類型的,默認是個ObjectId對象。
在一個集合裏面,每一個文檔都有惟一的"_id"值,來確保集合裏面每一個文檔都能被惟一標識。
MongoDB採用ObjectId,而不是其餘比較常規的作法(好比自動增長的主鍵)的主要緣由,由於在多個 服務器上同步自動增長主鍵值既費力還費時。
使用如下代碼生成新的ObjectId:
>newObjectId = ObjectId()
上面的語句返回如下惟一輩子成的id:
ObjectId("5349b4ddd2781d08c09890f3")
你也可使用生成的id來取代MongoDB自動生成的ObjectId:
>myObjectId = ObjectId("5349b4ddd2781d08c09890f4")
因爲 ObjectId 中存儲了 4 個字節的時間戳,因此你不須要爲你的文檔保存時間戳字段,你能夠經過 getTimestamp 函數來獲取文檔的建立時間:
>ObjectId("5349b4ddd2781d08c09890f4").getTimestamp()
以上代碼將返回 ISO 格式的文檔建立時間:
ISODate("2014-04-12T21:49:17Z")
在某些狀況下,您可能須要將ObjectId轉換爲字符串格式。你可使用下面的代碼:
>new ObjectId().str
以上代碼將返回Guid格式的字符串::
5349b4ddd2781d08c09890f3
Map-Reduce是一種計算模型,簡單的說就是將大批量的工做(數據)分解(MAP)執行,而後再將結果合併成最終結果(REDUCE)。
MongoDB提供的Map-Reduce很是靈活,對於大規模數據分析也至關實用。
如下是MapReduce的基本語法:
>db.collection.mapReduce( function() {emit(key,value);}, //map 函數 function(key,values) {return reduceFunction}, //reduce 函數 { out: collection, query: document, sort: document, limit: number } )
使用 MapReduce 要實現兩個函數 Map 函數和 Reduce 函數,Map 函數調用 emit(key, value), 遍歷 collection 中全部的記錄, 將 key 與 value 傳遞給 Reduce 函數進行處理。
Map 函數必須調用 emit(key, value) 返回鍵值對。
參數說明:
如下實例在集合 orders 中查找 status:"A" 的數據,並根據 cust_id 來分組,並計算 amount 的總和。
考慮如下文檔結構存儲用戶的文章,文檔存儲了用戶的 user_name 和文章的 status 字段:
>db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"active" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"active" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"active" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"active" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "mark", "status":"disabled" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "runoob", "status":"disabled" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "runoob", "status":"disabled" }) WriteResult({ "nInserted" : 1 }) >db.posts.insert({ "post_text": "菜鳥教程,最全的技術文檔。", "user_name": "runoob", "status":"active" }) WriteResult({ "nInserted" : 1 })
如今,咱們將在 posts 集合中使用 mapReduce 函數來選取已發佈的文章(status:"active"),並經過user_name分組,計算每一個用戶的文章數:
>db.posts.mapReduce( function() { emit(this.user_name,1); }, function(key, values) {return Array.sum(values)}, { query:{status:"active"}, out:"post_total" } )
以上 mapReduce 輸出結果爲:
{ "result" : "post_total", "timeMillis" : 23, "counts" : { "input" : 5, "emit" : 5, "reduce" : 1, "output" : 2 }, "ok" : 1 }
結果代表,共有 5 個符合查詢條件(status:"active")的文檔, 在map函數中生成了 5 個鍵值對文檔,最後使用reduce函數將相同的鍵值分爲 2 組。
具體參數說明:
使用 find 操做符來查看 mapReduce 的查詢結果:
>db.posts.mapReduce( function() { emit(this.user_name,1); }, function(key, values) {return Array.sum(values)}, { query:{status:"active"}, out:"post_total" } ).find()
以上查詢顯示以下結果,兩個用戶 tom 和 mark 有兩個發佈的文章:
{ "_id" : "mark", "value" : 4 } { "_id" : "runoob", "value" : 1 }
用相似的方式,MapReduce能夠被用來構建大型複雜的聚合查詢。
Map函數和Reduce函數可使用 JavaScript 來實現,使得MapReduce的使用很是靈活和強大。
全文檢索對每個詞創建一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先創建的索引進行查找,並將查找的結果反饋給用戶的檢索方式。
這個過程相似於經過字典中的檢索字表查字的過程。
MongoDB 從 2.4 版本開始支持全文檢索,目前支持15種語言(暫時不支持中文)的全文索引。
MongoDB 在 2.6 版本之後是默認開啓全文檢索的,若是你使用以前的版本,你須要使用如下代碼來啓用全文檢索:
>db.adminCommand({setParameter:true,textSearchEnabled:true})
或者使用命令:
mongod --setParameter textSearchEnabled=true
考慮如下 posts 集合的文檔數據,包含了文章內容(post_text)及標籤(tags):
{ "post_text": "enjoy the mongodb articles on Runoob", "tags": [ "mongodb", "runoob" ] }
咱們能夠對 post_text 字段創建全文索引,這樣咱們能夠搜索文章內的內容:
>db.posts.ensureIndex({post_text:"text"})
如今咱們已經對 post_text 創建了全文索引,咱們能夠搜索文章中的關鍵詞 runoob:
>db.posts.find({$text:{$search:"runoob"}})
如下命令返回了以下包含 runoob 關鍵詞的文檔數據:
{ "_id" : ObjectId("53493d14d852429c10000002"), "post_text" : "enjoy the mongodb articles on Runoob", "tags" : [ "mongodb", "runoob" ] }
若是你使用的是舊版本的 MongoDB,你可使用如下命令:
>db.posts.runCommand("text",{search:"runoob"})
使用全文索引能夠提升搜索效率。
刪除已存在的全文索引,可使用 find 命令查找索引名:
>db.posts.getIndexes()
經過以上命令獲取索引名,本例的索引名爲post_text_text,執行如下命令來刪除索引:
>db.posts.dropIndex("post_text_text")
正則表達式是使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。
許多程序設計語言都支持利用正則表達式進行字符串操做。
MongoDB 使用 $regex 操做符來設置匹配字符串的正則表達式。
MongoDB使用PCRE (Perl Compatible Regular Expression) 做爲正則表達式語言。
不一樣於全文檢索,咱們使用正則表達式不須要作任何配置。
考慮如下 posts 集合的文檔結構,該文檔包含了文章內容和標籤:
{ "post_text": "enjoy the mongodb articles on runoob", "tags": [ "mongodb", "runoob" ] }
如下命令使用正則表達式查找包含 runoob 字符串的文章:
>db.posts.find({post_text:{$regex:"runoob"}})
以上查詢也能夠寫爲:
>db.posts.find({post_text:/runoob/})
若是檢索須要不區分大小寫,咱們能夠設置 $options 爲 $i。
如下命令將查找不區分大小寫的字符串 runoob:
>db.posts.find({post_text:{$regex:"runoob",$options:"$i"}})
集合中會返回全部包含字符串 runoob 的數據,且不區分大小寫:
{ "_id" : ObjectId("53493d37d852429c10000004"), "post_text" : "hey! this is my post on runoob", "tags" : [ "runoob" ] }
咱們還能夠在數組字段中使用正則表達式來查找內容。 這在標籤的實現上很是有用,若是你須要查找包含以 run 開頭的標籤數據(ru 或 run 或 runoob), 你可使用如下代碼:
>db.posts.find({tags:{$regex:"run"}})
這裏面使用正則表達式有兩點須要注意:
正則表達式中使用變量。必定要使用eval將組合的字符串進行轉換,不能直接將字符串拼接後傳入給表達式。不然沒有報錯信息,只是結果爲空!實例以下:
var name=eval("/" + 變量值key +"/i");
如下是模糊查詢包含title關鍵詞, 且不區分大小寫:
title:eval("/"+title+"/i") // 等同於 title:{$regex:title,$Option:"$i"}
RockMongo是PHP5寫的一個MongoDB管理工具。
經過 Rockmongo 你能夠管理 MongoDB服務,數據庫,集合,文檔,索引等等。
它提供了很是人性化的操做。相似 phpMyAdmin(PHP開發的MySql管理工具)。
Rockmongo 下載地址:http://rockmongo.com/downloads
主要特徵:
參考文章:http://rockmongo.com/wiki/introduction?lang=zh_cn
GridFS 用於存儲和恢復那些超過16M(BSON文件限制)的文件(如:圖片、音頻、視頻等)。
GridFS 也是文件存儲的一種方式,可是它是存儲在MonoDB的集合中。
GridFS 能夠更好的存儲大於16M的文件。
GridFS 會將大文件對象分割成多個小的chunk(文件片斷),通常爲256k/個,每一個chunk將做爲MongoDB的一個文檔(document)被存儲在chunks集合中。
GridFS 用兩個集合來存儲一個文件:fs.files與fs.chunks。
每一個文件的實際內容被存在chunks(二進制數據)中,和文件有關的meta數據(filename,content_type,還有用戶自定義的屬性)將會被存在files集合中。
如下是簡單的 fs.files 集合文檔:
{ "filename": "test.txt", "chunkSize": NumberInt(261120), "uploadDate": ISODate("2014-04-13T11:32:33.557Z"), "md5": "7b762939321e146569b07f72c62cca4f", "length": NumberInt(646) }
如下是簡單的 fs.chunks 集合文檔:
{ "files_id": ObjectId("534a75d19f54bfec8a2fe44b"), "n": NumberInt(0), "data": "Mongo Binary Data" }
如今咱們使用 GridFS 的 put 命令來存儲 mp3 文件。 調用 MongoDB 安裝目錄下bin的 mongofiles.exe工具。
打開命令提示符,進入到MongoDB的安裝目錄的bin目錄中,找到mongofiles.exe,並輸入下面的代碼:
>mongofiles.exe -d gridfs put song.mp3
GridFS 是存儲文件的數據名稱。若是不存在該數據庫,MongoDB會自動建立。Song.mp3 是音頻文件名。
使用如下命令來查看數據庫中文件的文檔:
>db.fs.files.find()
以上命令執行後返回如下文檔數據:
{ _id: ObjectId('534a811bf8b4aa4d33fdf94d'), filename: "song.mp3", chunkSize: 261120, uploadDate: new Date(1397391643474), md5: "e4f53379c909f7bed2e9d631e15c1c41", length: 10401959 }
咱們能夠看到 fs.chunks 集合中全部的區塊,如下咱們獲得了文件的 _id 值,咱們能夠根據這個 _id 獲取區塊(chunk)的數據:
>db.fs.chunks.find({files_id:ObjectId('534a811bf8b4aa4d33fdf94d')})
以上實例中,查詢返回了 40 個文檔的數據,意味着mp3文件被存儲在40個區塊中。
MongoDB 固定集合(Capped Collections)是性能出色且有着固定大小的集合,對於大小固定,咱們能夠想象其就像一個環形隊列,當集合空間用完後,再插入的元素就會覆蓋最初始的頭部的元素!
咱們經過createCollection來建立一個固定集合,且capped選項設置爲true:
>db.createCollection("cappedLogCollection",{capped:true,size:10000})
還能夠指定文檔個數,加上max:1000屬性:
>db.createCollection("cappedLogCollection",{capped:true,size:10000,max:1000})
判斷集合是否爲固定集合:
>db.cappedLogCollection.isCapped()
若是須要將已存在的集合轉換爲固定集合可使用如下命令:
>db.runCommand({"convertToCapped":"posts",size:10000})
以上代碼將咱們已存在的 posts 集合轉換爲固定集合。
固定集合文檔按照插入順序儲存的,默認狀況下查詢就是按照插入順序返回的,也可使用$natural調整返回順序。
>db.cappedLogCollection.find().sort({$natural:-1})
能夠插入及更新,但更新不能超出collection的大小,不然更新失敗,不容許刪除,可是能夠調用drop()刪除集合中的全部行,可是drop後須要顯式地重建集合。
在32位機子上一個cappped collection的最大值約爲482.5M,64位上只受系統文件大小的限制。
MongoDB 沒有像 SQL 同樣有自動增加的功能, MongoDB 的 _id 是系統自動生成的12字節惟一標識。
但在某些狀況下,咱們可能須要實現 ObjectId 自動增加功能。
因爲 MongoDB 沒有實現這個功能,咱們能夠經過編程的方式來實現,如下咱們將在 counters 集合中實現_id字段自動增加。
考慮如下 products 文檔。咱們但願 _id 字段實現 從 1,2,3,4 到 n 的自動增加功能。
{ "_id":1, "product_name": "Apple iPhone", "category": "mobiles" }
爲此,建立 counters 集合,序列字段值能夠實現自動長:
>db.createCollection("counters")
如今咱們向 counters 集合中插入如下文檔,使用 productid 做爲 key:
{ "_id":"productid", "sequence_value": 0 }
sequence_value 字段是序列經過自動增加後的一個值。
使用如下命令插入 counters 集合的序列文檔中:
>db.counters.insert({_id:"productid",sequence_value:0})
如今,咱們建立函數 getNextSequenceValue 來做爲序列名的輸入, 指定的序列會自動增加 1 並返回最新序列值。在本文的實例中序列名爲 productid 。
>function getNextSequenceValue(sequenceName){ var sequenceDocument = db.counters.findAndModify( { query:{_id: sequenceName }, update: {$inc:{sequence_value:1}}, new:true }); return sequenceDocument.sequence_value; }
接下來咱們將使用 getNextSequenceValue 函數建立一個新的文檔, 並設置文檔 _id 自動爲返回的序列值:
>db.products.insert({ "_id":getNextSequenceValue("productid"), "product_name":"Apple iPhone", "category":"mobiles"}) >db.products.insert({ "_id":getNextSequenceValue("productid"), "product_name":"Samsung S3", "category":"mobiles"})
就如你所看到的,咱們使用 getNextSequenceValue 函數來設置 _id 字段。
爲了驗證函數是否有效,咱們可使用如下命令讀取文檔:
>db.products.find()
以上命令將返回如下結果,咱們發現 _id 字段是自增加的:
{ "_id" : 1, "product_name" : "Apple iPhone", "category" : "mobiles"} { "_id" : 2, "product_name" : "Samsung S3", "category" : "mobiles" }