MongoDB通過查詢與游標(biāo)徹底玩轉(zhuǎn)分布式文件存儲
MongoDB簡介
MongoDB是一個(gè)基于分布式文件存儲的數(shù)據(jù)庫。由C++語言編寫。旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲解決方案。
MongoDB是一個(gè)介于關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫當(dāng)中功能最豐富,最像關(guān)系數(shù)據(jù)庫的,它支持的數(shù)據(jù)結(jié)構(gòu)非常松散,是類似json的bson格式,因此可以存儲比較復(fù)雜的數(shù)據(jù)類型。
MongoDB最大的特點(diǎn)是它支持的查詢語言非常強(qiáng)大,其語法有點(diǎn)類似于面向?qū)ο蟮牟樵冋Z言,幾乎可以實(shí)現(xiàn)類似關(guān)系數(shù)據(jù)庫單表查詢的絕大部分功能,而且還支持對數(shù)據(jù)建立索引。
官網(wǎng):MongoDB: The Developer Data Platform | MongoDB | MongoDB
| 指標(biāo)項(xiàng) | 指標(biāo)值 | 說明 |
|---|---|---|
| 開發(fā)語言 | C++ | / |
| 使用方式 | 服務(wù) | 服務(wù)(獨(dú)立運(yùn)行)還是組件(代碼集成) |
| 部署方式 | 支持Windows/Linux/Docker | 如果是服務(wù),則是否支持 Windows/Linux/Docker 部署 |
| 許可協(xié)議 | SSPL | Apache/MIT/GNU/SSPL/... |
| 是否有商業(yè)版 | 有 | / |
| 最近迭代時(shí)間 | 2022/2/12 | 該組件最后一次更新時(shí)間是什么時(shí)候 |
| 社區(qū)關(guān)注度 | 21.2k | 該組件在 Github/Gitlab 中的 Star 數(shù)是多少 |
1.MongoDB主要特點(diǎn)
1.1文檔數(shù)據(jù)庫
使用文檔的優(yōu)點(diǎn)是
- 文檔(即對象)對應(yīng)于許多編程語言中的本機(jī)數(shù)據(jù)類型。
- 嵌入式文檔和數(shù)組減少了對昂貴連接的需求。
- 動態(tài)模式支持流暢的多態(tài)性。
1.2高性能
MongDB提供高性能的數(shù)據(jù)持久性。特別是,
- 對嵌入式數(shù)據(jù)模型的支持減少了數(shù)據(jù)庫系統(tǒng)上的 I/O活動。
- 索引支持更快的查詢,并且可以包含來自嵌入文檔和數(shù)組的鍵。
1.3高可用性
MongDB的復(fù)制工具,稱為副本集(一組 MongoDB 服務(wù)器,它們維護(hù)相同的數(shù)據(jù)集,提供冗余并提高數(shù)據(jù)可用性),提供自動故障轉(zhuǎn)移和數(shù)據(jù)冗余。
1.4 水平可擴(kuò)展
MongoDB 提供水平可擴(kuò)展性。
1.5支持多個(gè)存儲引擎
MongoDB支持多種存儲引擎:WiredTiger存儲引擎(包括對靜態(tài)加密的支持)和內(nèi)存存儲引擎。
此外,MongoDB 提供可插拔的存儲引擎 API,允許第三方為 MongoDB 開發(fā)存儲引擎。
2.應(yīng)用場景
1)社交場景,使用MongoDB存儲用戶信息,以及用戶發(fā)表的朋友圈信息,通過地理位置索引實(shí)現(xiàn)附近的人、地點(diǎn)等功能。
2)游戲場景,使用MongoDB存儲游戲用戶信息,用戶的裝備、積分等直接以內(nèi)嵌文檔的形式存儲,方便查詢、高效率存儲和訪問。
3)物流場景,使用 MongoDB 存儲訂單信息,訂單狀態(tài)在運(yùn)送過程中會不斷更新,以 MongoDB 內(nèi)嵌數(shù)組的形式來存儲,一次查詢就能將 訂單所有的變更讀取出來。
4)物聯(lián)網(wǎng)場景,使用 MongoDB 存儲所有接入的智能設(shè)備信息,以及設(shè)備匯報(bào)的日志信息,并對這些信息進(jìn)行多維度的分析。
5)視頻直播,使用 MongoDB 存儲用戶信息、點(diǎn)贊互動信息等。
這些應(yīng)用場景中,數(shù)據(jù)操作方面的共同特點(diǎn)是:
(1)數(shù)據(jù)量大
(2)寫入操作頻繁(讀寫都很頻繁)
(3)價(jià)值較低的數(shù)據(jù),對事務(wù)性要求不高
對于這樣的數(shù)據(jù),我們更適合使用MongoDB來實(shí)現(xiàn)數(shù)據(jù)的存儲
https://pippichi.github.io/pdf/mongodb_base.pdf
下面重點(diǎn)介紹下MongoDB通過查詢與游標(biāo)徹底玩轉(zhuǎn)分布式文件存儲。
MongoDB通過查詢與游標(biāo)徹底玩轉(zhuǎn)分布式文件存儲
一、查詢
1、find()基本用法
查詢就是返回集合中文檔的一個(gè)子集,子集的范圍從0個(gè)文檔到整個(gè)集合。要返回哪些文檔由find的第一個(gè)參數(shù)決定,該參數(shù)是一個(gè)用于指定查詢條件的文檔。
如果是空,則返回全部文檔。
當(dāng)向查詢文檔中添加鍵值對時(shí),就意味著限定了查詢條件。例如db.users.find({"name":"哪吒編程"})
可以在查詢文檔時(shí),傳入多個(gè)鍵值對,相當(dāng)于關(guān)系型數(shù)據(jù)庫中的where ... and ...。
2、指定要返回的鍵
有時(shí)候,只想查詢文檔中的部分鍵
> db.users.find({},{"id":1,"dept":1})
{ "_id" : ObjectId("638b2822bb535f1c23f9b09a"), "id" : "1", "dept" : [ { "name" : "哪吒編程", "age" : 18, "address" : "大連" }, { "name" : "云韻", "age" : 19, "address" : "大連" }, { "name" : "美杜莎", "age" : 28, "address" : "北京" } ] }
{ "_id" : ObjectId("638b3944bb535f1c23f9b09b"), "id" : "1", "dept" : [ { "name" : "哪吒編程", "age" : 18, "address" : "大連" }, { "name" : "云韻", "age" : 19, "address" : "大連" }, { "name" : "美杜莎", "age" : 28, "address" : "北京" } ] }
> db.users.find({},{"_id":0,"dept":1})
{ "dept" : [ { "name" : "哪吒編程", "age" : 18, "address" : "大連" }, { "name" : "云韻", "age" : 19, "address" : "大連" }, { "name" : "美杜莎", "age" : 28, "address" : "北京" } ] }
{ "dept" : [ { "name" : "哪吒編程", "age" : 18, "address" : "大連" }, { "name" : "云韻", "age" : 19, "address" : "大連" }, { "name" : "美杜莎", "age" : 28, "address" : "北京" } ] }3、查詢條件
$lt、$lte、$gt、$gte都屬于比較運(yùn)算符,分別對應(yīng)<、<=、>、>=。
可以將其組合使用以查找一個(gè)范圍內(nèi)的值。
> db.users.find({"dept.age":{"$gte":20,"$lte":30}})4、or查詢
MongoDB中有兩種方式可以進(jìn)行or查詢。$in可以用來查詢一個(gè)鍵的多個(gè)值。$or則更通用一些,可以在多個(gè)鍵中查詢?nèi)我獾慕o定值。
> db.users.find({"id":{"$in":["1","3"]}})
{ "_id" : ObjectId("638b2822bb535f1c23f9b09a"), "id" : "1", "dept" : [ { "name" : "哪吒編程", "age" : 18, "address" : "大連" }, { "name" : "云韻", "age" : 19, "address" : "大連" }, { "name" : "美杜莎", "age" : 28, "address" : "北京" } ] }
{ "_id" : ObjectId("638b3944bb535f1c23f9b09b"), "id" : "1", "dept" : [ { "name" : "哪吒編程", "age" : 18, "address" : "大連" }, { "name" : "云韻", "age" : 19, "address" : "大連" }, { "name" : "美杜莎", "age" : 28, "address" : "北京" } ] }
{ "_id" : ObjectId("638b4cacbb535f1c23f9b09c"), "id" : "3", "dept" : [ { "name" : "哪吒編程", "age" : 18, "address" : "大連" }, { "name" : "云韻", "age" : 19, "address" : "大連" }, { "name" : "美杜莎", "age" : 28, "address" : "北京" } ] }
>5、$not
$not是一個(gè)元條件運(yùn)算符,可以用于任何其它條件之上。
二、特定類型的查詢
1、null
null的行為有一些特別。它可以與自身匹配。
> db.users.find({"dept":null})
{ "_id" : ObjectId("638b538682bdbdfa72665a11"), "id" : "1", "dept" : null }2、正則表達(dá)式
"$regex"可以在查詢中為字符串的模式匹配提供正則表達(dá)式功能。正則表達(dá)式對于靈活的字符串匹配非常有用。
> db.users.find({"name":{"$regex":"哪吒"}}))
{ "_id" : ObjectId("638b549982bdbdfa72665a12"), "id" : "1", "name" : "哪吒編程", "age" : 18 }
{ "_id" : ObjectId("638b54cd82bdbdfa72665a15"), "id" : "1", "name" : "CSDN哪吒", "age" : 18 }MongoDB會使用Perl兼容的正則表達(dá)式(PRCE)庫來對正則表達(dá)式進(jìn)行匹配。任何PCRE支持的正則表達(dá)式語法都能被MongoDB接受。
3、查詢數(shù)組
$all可以通過多個(gè)元素匹配數(shù)組。
> db.workers.find({name:{$all:["哪吒編程","云韻"]}})
{ "_id" : ObjectId("638b2154bb535f1c23f9b098"), "id" : "1", "name" : [ "哪吒編程", "云韻" ] }
{ "_id" : ObjectId("638b59fc82bdbdfa72665a16"), "id" : "1", "name" : [ "哪吒編程", "云韻", "美杜莎" ] }
{ "_id" : ObjectId("638b59fc82bdbdfa72665a17"), "id" : "2", "name" : [ "哪吒編程", "云韻", "納蘭嫣然" ] }如果想在數(shù)組中查詢特定位置的元素,可以使用key.index語法來指定下標(biāo):
> db.workers.find({"name.2":"美杜莎"})
{ "_id" : ObjectId("638b59fc82bdbdfa72665a16"), "id" : "1", "name" : [ "哪吒編程", "云韻", "美杜莎" ] }
通過$size指定要查找的數(shù)組的大?。?/p>
> db.workers.find({"name":{"$size":2}})
{ "_id" : ObjectId("638b2154bb535f1c23f9b098"), "id" : "1", "name" : [ "哪吒編程", "云韻" ] }4、數(shù)組與范圍查找的相互作用
先舉一個(gè)例子:
> db.student.find()
{ "_id" : ObjectId("638b6b8382bdbdfa72665a19"), "id" : "1", "name" : "哪吒編程", "age" : 18 }
{ "_id" : ObjectId("638b6b8482bdbdfa72665a1a"), "id" : "2", "name" : "云韻", "age" : 23 }
{ "_id" : ObjectId("638b6b8482bdbdfa72665a1b"), "id" : "3", "name" : "美杜莎", "age" : [ 15, 29 ] }
{ "_id" : ObjectId("638b6b8582bdbdfa72665a1c"), "id" : "3", "name" : "蕭炎", "age" : 38 }
> db.student.find({"age":{"$gt":20,"$lt":28}})
{ "_id" : ObjectId("638b6b8482bdbdfa72665a1a"), "id" : "2", "name" : "云韻", "age" : 23 }
{ "_id" : ObjectId("638b6b8482bdbdfa72665a1b"), "id" : "3", "name" : "美杜莎", "age" : [ 15, 29 ] }和想象中的不太一樣啊,我的本意是查詢年齡在20~28之間的人,為什么呢?
文檔中的標(biāo)量(非數(shù)組元素)必須與查詢條件中的每一條子句相匹配。如果使用db.student.find({"age":{"$gt":20,"$lt":28}})進(jìn)行查詢,那么age必須介于20~28之間,然而,如果age是一個(gè)數(shù)組,那么當(dāng)age鍵中的某一個(gè)元素與查詢條件的任意一條語句相匹配時(shí),文檔也會被返回。(即15<28,29大于20),完美適配。
這樣就會使針對數(shù)組的范圍查詢失去了作用。
此時(shí),可以使用"$elemMatch"強(qiáng)制MongoDB將這兩個(gè)子句與單個(gè)數(shù)組元素進(jìn)行比較。不過,"$elemMatch"不會匹配非數(shù)組元素。
-- 返回空
db.student.find({"age":{"$elemMatch":{"$gt":20,"$lt":28}}})如果在查詢的字段上有索引,那么可以使用min和max將查詢條件遍歷的索引范圍限制為"$gt"和"$lt"的值。
db.student.find({"age":{"$gt":20,"$lt":28}}).min({"age":20}).max({"age":28})現(xiàn)在,這條查詢語句只會遍歷值在20~28之間的索引。
三、游標(biāo)
數(shù)據(jù)庫會使用游標(biāo)返回find的執(zhí)行結(jié)果。游標(biāo)的客戶端實(shí)現(xiàn)通常能夠在很大程度上對查詢的最終輸出進(jìn)行控制。你可以限制結(jié)果的數(shù)量,跳過一些結(jié)果,按任意方向的任意鍵組合對結(jié)果進(jìn)行排序,以及執(zhí)行徐國其他功能強(qiáng)大的操作。
通過cursor.hasNext()檢查是否還有其它結(jié)果,通過cursor.next()用來對其進(jìn)行獲取。
調(diào)用find()時(shí),shell并不會立即查詢數(shù)據(jù)庫,而是等到真正開始請求結(jié)果時(shí)才發(fā)送查詢,這樣可以在執(zhí)行之前給查詢附加額外的選項(xiàng)。cursor對象的大多數(shù)方法會返回游標(biāo)本身,這樣就可以按照任意順序?qū)⑦x項(xiàng)鏈接起來了。
在使用db.users.find();查詢時(shí),實(shí)際上查詢并沒有真正執(zhí)行,只是在構(gòu)造查詢,執(zhí)行cursor.hasNext(),查詢才會發(fā)往服務(wù)器端。shell會立刻獲取前100個(gè)結(jié)果或者前4MB的數(shù)據(jù)(兩者之中的較小者),這樣下次調(diào)用next或者h(yuǎn)asNext時(shí)就不必再次連接服務(wù)器去獲取結(jié)果了。在客戶端遍歷完第一組結(jié)果后,shell會再次連接數(shù)據(jù)庫,使用getMore請求更多的結(jié)果。getMore請求包含一個(gè)游標(biāo)的標(biāo)識符,它會向數(shù)據(jù)庫詢問是否還有更多的結(jié)果,如果有則返回下一批結(jié)果。這個(gè)過程會一直持續(xù),直到游標(biāo)耗盡或者結(jié)果被全部返回。
四、游標(biāo)的生命周期
在服務(wù)器端,游標(biāo)會占用內(nèi)存和資源。一旦游標(biāo)遍歷完結(jié)果之后,或者客戶端發(fā)送一條消息要求終止,數(shù)據(jù)庫就可以釋放它正在使用的資源。
何時(shí)銷毀游標(biāo):
- 當(dāng)游標(biāo)遍歷完匹配的結(jié)果時(shí),它會消除自身;
- 當(dāng)游標(biāo)超出客戶端的作用域時(shí),驅(qū)動程序會向數(shù)據(jù)庫發(fā)送一條特殊的消息,讓數(shù)據(jù)庫終止該游標(biāo);
- 如果10分鐘沒有被使用的話,數(shù)據(jù)庫游標(biāo)也將自動銷毀;
五、limit、skip、soat
1、常用的查詢選項(xiàng)
最常用的查詢選項(xiàng)是限制返回結(jié)果的數(shù)量、略過一定數(shù)量的結(jié)果以及排序。所有這些選項(xiàng)必須在查詢被發(fā)送到數(shù)據(jù)庫之前指定。
- limit:限制數(shù)量;
- skip:略過;
- soat:排序,1是升序,-1是降序;
使用skip略過少量的文檔是可以的,但對于結(jié)果非常多的情況,skip會非常慢,因?yàn)橐紫日业奖宦赃^的結(jié)果,然后再丟棄這些數(shù)據(jù)。
2、使用skip進(jìn)行分頁
最簡單的分頁方式是
> db.student.find().sort({"id":1}).limit(5)
{ "_id" : ObjectId("638b6b8382bdbdfa72665a19"), "id" : "1", "name" : "哪吒編程", "age" : 18 }
{ "_id" : ObjectId("638c6685e96330d24f819176"), "id" : "1", "name" : "哪吒編程", "age" : 18 }
{ "_id" : ObjectId("638c6685e96330d24f81917f"), "id" : "10", "name" : "云韻", "age" : 23 }
{ "_id" : ObjectId("638c6685e96330d24f819180"), "id" : "11", "name" : "美杜莎", "age" : 29 }
{ "_id" : ObjectId("638c6686e96330d24f819181"), "id" : "12", "name" : "蕭炎", "age" : 38 }
> db.student.find().sort({"id":1}).skip(5).limit(5)
{ "_id" : ObjectId("638b6b8482bdbdfa72665a1a"), "id" : "2", "name" : "云韻", "age" : 23 }
{ "_id" : ObjectId("638c6685e96330d24f819177"), "id" : "2", "name" : "云韻", "age" : 23 }
{ "_id" : ObjectId("638b6b8582bdbdfa72665a1c"), "id" : "3", "name" : "蕭炎", "age" : 38 }
{ "_id" : ObjectId("638b6b8482bdbdfa72665a1b"), "id" : "3", "name" : "美杜莎", "age" : [ 15, 29 ] }
{ "_id" : ObjectId("638c6685e96330d24f819178"), "id" : "3", "name" : "美杜莎", "age" : 29 }
> db.student.find().sort({"id":1}).skip(10).limit(5)
{ "_id" : ObjectId("638c6685e96330d24f819179"), "id" : "4", "name" : "蕭炎", "age" : 38 }
{ "_id" : ObjectId("638c6685e96330d24f81917a"), "id" : "5", "name" : "哪吒編程", "age" : 18 }
{ "_id" : ObjectId("638c6685e96330d24f81917b"), "id" : "6", "name" : "云韻", "age" : 23 }
{ "_id" : ObjectId("638c6685e96330d24f81917c"), "id" : "7", "name" : "美杜莎", "age" : 29 }
{ "_id" : ObjectId("638c6685e96330d24f81917d"), "id" : "8", "name" : "蕭炎", "age" : 38 }
>3、不用skip進(jìn)行分頁
可以通過以下方式:
var lastTime = null;
while(page.hasNext){
lastTime = page.next();
...
}
var page1 = db.student.find({"date":{"$lt":lastTime.date}});
page1.sort({"date":-1}).limit(5);到此這篇關(guān)于MongoDB查詢與游標(biāo),徹底玩轉(zhuǎn)分布式文件存儲的文章就介紹到這了,更多相關(guān)MongoDB分布式文件存儲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解MongoDB中用sharding將副本集分配至服務(wù)器集群的方法
副本集是MongoDB的主從復(fù)制中的重要功能,經(jīng)常被用來作額外的備份,這里我們就來詳解MongoDB中用sharding將副本集分配至服務(wù)器集群的方法,首先還是來回顧一下MongoDB中副本集的基本知識:2016-07-07
CentOS 6.5系統(tǒng)中使用yum安裝MongoDB 2.6 教程
這篇文章主要介紹了CentOS 6.5系統(tǒng)中使用yum安裝MongoDB 2.6 教程,本文共分5個(gè)步驟完成MongoDB的安裝,需要的朋友可以參考下2015-01-01
MongoDB學(xué)習(xí)筆記之MapReduce使用示例
這篇文章主要介紹了MongoDB學(xué)習(xí)筆記之MapReduce使用示例,本文直接給出實(shí)例代碼,需要的朋友可以參考下2015-07-07
MongoDB中MapReduce編程模型使用實(shí)例
作為一個(gè)優(yōu)秀的編程模型,MapReduce在大數(shù)據(jù)處理中有很大的優(yōu)勢,而mongodb也支持這一編程模型,本文通過簡單的單詞計(jì)數(shù)示例論述在mongodb中如何使用MapReduce2014-04-04
MongoDB使用$addToSet向數(shù)組中添加元素的操作代碼
使用方法$addToSet, 向數(shù)組中添加不存在的元素,如果元素已經(jīng)存在于目標(biāo)數(shù)組當(dāng)中,則使用$addToSet不會更新當(dāng)前文檔,本文給大家介紹了MongoDB使用$addToSet向數(shù)組中添加元素的操作代碼,感興趣的小伙伴跟著小編一起來看看吧2024-06-06
MongoDB數(shù)據(jù)庫類replace替換字符串指定內(nèi)容
mongoDB是沒有定義replace函數(shù)的,那么如果有需求需要替換nongo中數(shù)據(jù)的某一部分,怎么辦?下面這篇文章主要給大家介紹了關(guān)于MongoDB數(shù)據(jù)庫類replace替換字符串指定內(nèi)容的相關(guān)資料,需要的朋友可以參考下2023-05-05
MongoDB orm框架的注意事項(xiàng)及簡單使用
MongoDB官方提供的orm的輕量級封裝的 zfoo orm 框架,只對官方提供的進(jìn)行了簡單的封裝,還做了一些官方不支持的語法校驗(yàn)。本文介紹了該框架的注意事項(xiàng)及簡單使用2021-06-06

