(2022.08.26 Thur)
本文包括
- mongoDB的應(yīng)用場(chǎng)景
- 數(shù)據(jù)架構(gòu)
- 高可用與高擴(kuò)展
- 基礎(chǔ)語(yǔ)法、索引
- 存儲(chǔ)引擎
- ObjectID對(duì)象
等
MongoDB是一個(gè)基于分布式文件存儲(chǔ)的數(shù)據(jù)庫(kù)衙耕。用C++語(yǔ)言編寫(xiě)昧穿。旨在為WEB應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案。
MongoDB是一個(gè)介于關(guān)系數(shù)據(jù)庫(kù)和非關(guān)系數(shù)據(jù)庫(kù)之間的產(chǎn)品橙喘,是非關(guān)系數(shù)據(jù)庫(kù)當(dāng)中功能最豐富时鸵,最像關(guān)系數(shù)據(jù)庫(kù)的。它支持的數(shù)據(jù)結(jié)構(gòu)非常松散,是類(lèi)似json的bson格式饰潜,因此可以存儲(chǔ)比較復(fù)雜的數(shù)據(jù)類(lèi)型初坠。Mongo最大的特點(diǎn)是它支持的查詢(xún)語(yǔ)言非常強(qiáng)大,其語(yǔ)法有點(diǎn)類(lèi)似于面向?qū)ο蟮牟樵?xún)語(yǔ)言彭雾,幾乎可以實(shí)現(xiàn)類(lèi)似關(guān)系數(shù)據(jù)庫(kù)單表查詢(xún)的絕大部分功能碟刺,而且還支持對(duì)數(shù)據(jù)建立索引。
mongoDB的缺點(diǎn)是占用空間比SQL大薯酝。
mongoDB的應(yīng)用場(chǎng)景
以MongoDB為代表的文檔數(shù)據(jù)庫(kù)最大特點(diǎn)是no-schema半沽,可以存儲(chǔ)和讀取任意的數(shù)據(jù),目前絕大多數(shù)文檔數(shù)據(jù)庫(kù)存儲(chǔ)的數(shù)據(jù)格式是JSON/BSON吴菠,因?yàn)镴SON是自描述的者填,無(wú)需在使用前定義字段。
no-schema的特點(diǎn)帶來(lái)了一些優(yōu)勢(shì):
- 新增字段簡(jiǎn)單
- 歷史數(shù)據(jù)不會(huì)出錯(cuò)
- 可以容易存儲(chǔ)復(fù)雜數(shù)據(jù)
文檔數(shù)據(jù)庫(kù)的缺點(diǎn)之一是不支持事務(wù)做葵,對(duì)事務(wù)要求嚴(yán)格的場(chǎng)景不適合使用文檔數(shù)據(jù)庫(kù)幔托。另一個(gè)缺點(diǎn)是無(wú)法使用SQL中的join操作。更適合作為SQL數(shù)據(jù)庫(kù)的補(bǔ)充蜂挪。
數(shù)據(jù)架構(gòu)
磁盤(pán)文件經(jīng)過(guò)加載之后形成 MongoDB實(shí)例,實(shí)例中可以存放多個(gè)數(shù)據(jù)庫(kù)(圖示僅展示一個(gè)數(shù)據(jù)庫(kù))嗓化。每個(gè)數(shù)據(jù)庫(kù)中存放的是Collection棠涮,集合中存放Document,Document 中存放 Field刺覆。
這里提到的集合严肪、文檔、字段等與SQL對(duì)應(yīng)關(guān)系如下
SQL術(shù)語(yǔ) | mongoDB術(shù)語(yǔ) |
---|---|
database | database |
table | collection |
row | document |
volume/field | field |
高可用與高擴(kuò)展
MongoDB 的數(shù)據(jù)復(fù)制架構(gòu)是保障 MongoDB 實(shí)現(xiàn)數(shù)據(jù)保護(hù)的重要基礎(chǔ)條件谦屑。
復(fù)制集(Replica Set)是mongoDB的數(shù)據(jù)復(fù)制架構(gòu)驳糯。通常是三個(gè)對(duì)等的節(jié)點(diǎn)構(gòu)成一個(gè)復(fù)制集,有Primary和Secondary兩種角色氢橙,其中 Primary負(fù)責(zé)讀寫(xiě)請(qǐng)求酝枢,Secondary負(fù)責(zé)讀請(qǐng)求,可以通過(guò)配置實(shí)現(xiàn)悍手。Primary和Secondary節(jié)點(diǎn)之間在數(shù)據(jù)寫(xiě)入過(guò)程當(dāng)中實(shí)現(xiàn)數(shù)據(jù)的異步復(fù)制帘睦。節(jié)點(diǎn)之間通過(guò)Heartbeat實(shí)現(xiàn)健康偵測(cè),當(dāng)Primary失敗坦康,集群可以通過(guò)多數(shù)派選舉新的Primary竣付,并且實(shí)現(xiàn)Failover機(jī)制。
我們?cè)賮?lái)看現(xiàn)實(shí)場(chǎng)景當(dāng)中使用比較多的相對(duì)比較復(fù)雜的分切分布式集群架構(gòu)滞欠,也就是高擴(kuò)展架構(gòu)
從圖示架構(gòu)可以看出古胆,分片集群的優(yōu)勢(shì)在于提供類(lèi)似線(xiàn)性增長(zhǎng)的架構(gòu),提高數(shù)據(jù)可用性筛璧,提高大型數(shù)據(jù)庫(kù)查詢(xún)服務(wù)器的性能逸绎。當(dāng) MongoDB 單點(diǎn)數(shù)據(jù)庫(kù)服務(wù)器存儲(chǔ)成為瓶頸惹恃、單點(diǎn)數(shù)據(jù)庫(kù)服務(wù)器的性能成為瓶頸或需要部署大型應(yīng)用以充分利用內(nèi)存時(shí),可以使用分片技術(shù)桶良。
整體架構(gòu)有幾個(gè)重要的組件:切片(Shard)座舍、配置服務(wù)器(ConfigServer、路由(Query Router)陨帆。那么他們的邏輯關(guān)系又是什么樣的呢曲秉?各自承擔(dān)了什么的角色呢?
- Shard :用于存儲(chǔ)實(shí)際的數(shù)據(jù)塊疲牵,一個(gè)切片服務(wù)器角色可由幾臺(tái)機(jī)器組成承二,防止主機(jī)單點(diǎn)故障。
- Config Server :MongoDB 實(shí)例纲爸,存儲(chǔ)了整個(gè) ClusterMetadata 亥鸠,其中包括 chunk 信息。
- Query Routers :客戶(hù)端由此接入识啦,且讓整個(gè)集群看上去像單一數(shù)據(jù)庫(kù)负蚊,前端應(yīng)用可以透明使用。
基于以上組件功能角色颓哮,我們來(lái)分析客戶(hù)端的訪(fǎng)問(wèn)路徑為:首先家妆、客戶(hù)端訪(fǎng)問(wèn)路由( Query Router )的統(tǒng)一接口層,由路由層將數(shù)據(jù)請(qǐng)求發(fā)送到特定的配置服務(wù)器( ConfigServers )冕茅;接著伤极,由配置服務(wù)器查詢(xún)本地的元數(shù)據(jù)信息定位到要訪(fǎng)問(wèn)的數(shù)據(jù)在哪個(gè)切片服務(wù)器( Shard )上;最后姨伤,客戶(hù)端直接訪(fǎng)問(wèn)到切片服務(wù)器的具體位置技肩,獲取自己所需的數(shù)據(jù)信息悦穿。
MongoDB 的數(shù)據(jù)劃分锦聊,是以集合級(jí)別為標(biāo)準(zhǔn)丛楚。分片通過(guò) Shard Key 來(lái)劃分集合數(shù)據(jù)。具體切片的策略可以是通過(guò)數(shù)據(jù)的范圍劃分來(lái)切分炊豪,也可以通過(guò)哈希策略來(lái)切分凌箕,具體需要考慮到數(shù)據(jù)的特點(diǎn)和集群數(shù)據(jù)訪(fǎng)問(wèn)的效率。
基礎(chǔ)語(yǔ)法词渤、索引
(2022.08.29 Mon)
在docker的bash環(huán)境中進(jìn)入mongodb
>> docker exec -it <image_id> /bin/bash
>> mongo
基本查看
查看數(shù)據(jù)庫(kù)牵舱、collections
> show databses;
> show dbs;
> use <db_name>; # 進(jìn)入某數(shù)據(jù)庫(kù)
> show collections;
> show tables; # 與show collections等效
新增
創(chuàng)數(shù)據(jù)庫(kù)和collections
> db.createCollection('<collection_name>'); # 創(chuàng)建collection
新增collection中的文本
> data = {'name': 'abc', 'age': 100, 'genre': 'pop'}
> db.<coll_name>.insert(data);
WriteResult({ "nInserted" : 1 })
執(zhí)行insert
操作之后,mongdoDB系統(tǒng)會(huì)自動(dòng)為這條記錄添加一個(gè)id缺虐,_id
芜壁。因此,即便添加的兩條記錄的字段和內(nèi)容完全一致,也會(huì)因?yàn)?code>_id的不同而作為不同的文本存在慧妄。
查詢(xún)
- 展示collection中的所有信息
> db.<coll_name>.find();
> db.<coll_name>.find().pretty(); # 展示格式經(jīng)過(guò)美化
- 根據(jù)特定條件查詢(xún)信息
> cond = {'b': 103};
> db.<coll_name>.find(cond);
> db.testdb.find(cond);
{ "_id" : ObjectId("630c6f6499e641685ec2b80b"), "b" : 103 }
{ "_id" : ObjectId("630c76f099e641685ec2b80d"), "b" : 103, "test" : 999, "age" : 18 }
根據(jù)條件指定的范圍查詢(xún)信息顷牌,需要采用諸如
{key: {$xx: value}};
的格式來(lái)指定查詢(xún)條件的變量和范圍。其中的xx
代表了范圍塞淹,大于gt
窟蓝,小于lt
,大于等于gte
饱普,小于等于lte
运挫,不等于ne
,等于eq
套耕,反not
谁帕。比如查詢(xún)b
大于101的所有記錄。
> cond = {'b': {$gt: 101}};
> db.<coll_name>.find(cond);
{ "_id" : ObjectId("630c5f4299e641685ec2b808"), "b" : 102 }
{ "_id" : ObjectId("630c61e1529d851b783347f2"), "b" : 103, "text" : 1 }
{ "_id" : ObjectId("630c76f099e641685ec2b80d"), "b" : 103, "test" : 999, "age" : 18 }
查詢(xún)b
不等于102的所有記錄冯袍。
> cond = {'b': {$ne: 102}};
> cond1 = {'b': {$not: {$eq: 102}}}; # cond和cond1等價(jià)
> db.<>.find(cond);
{ "_id" : ObjectId("630c5dd599e641685ec2b806"), "datatime" : "2022-04-12", "location" : "Harbin", "event" : "terminate contract", "db" : "mongodb" }
{ "_id" : ObjectId("630c5f3099e641685ec2b807"), "b" : 101 }
{ "_id" : ObjectId("630c61e1529d851b783347f2"), "b" : 103, "text" : 1 }
{ "_id" : ObjectId("630c76f099e641685ec2b80d"), "b" : 103, "test" : 999, "age" : 18 }
根據(jù)多個(gè)條件查詢(xún)匈挖。條件之間可以有多種關(guān)系,1) and康愤,2) or儡循。不同的條件分別用字典存儲(chǔ),寫(xiě)成{key: value}
的格式征冷,并保存在一個(gè)列表中[ ]
贮折。
db.<coll_name>.find({$xx: [{key1: value1},{key2: {$xx: value}}]});
多個(gè)條件同時(shí)滿(mǎn)足,使用and
關(guān)鍵字
> db.testdb.find({$and: [{'b': {$gt:100}},{'test':111}]});
{ "_id" : ObjectId("630c6fbc99e641685ec2b80c"), "b" : 103, "test" : 111 }
多個(gè)條件可單獨(dú)滿(mǎn)足资盅,使用or
關(guān)鍵字
> db.testdb.find({$or: [{'b': {$gt:101}},{'test':111}]});
{ "_id" : ObjectId("630c5f4299e641685ec2b808"), "b" : 102 }
{ "_id" : ObjectId("630c61e1529d851b783347f2"), "b" : 103, "text" : 1 }
{ "_id" : ObjectId("630c76f099e641685ec2b80d"), "b" : 103, "test" : 999, "age" : 18 }
刪除
刪除數(shù)據(jù)庫(kù)和collection
> db.dropDatabase(); # 刪除db
> db.<coll_name>.drop(); # 刪除collection
刪除文檔,使用命令如
cond = {key: value};
db.<coll_name>.remove(cond, {justOne: <value=0>, writeConcern: <value>});
刪除文檔時(shí)踊赠,通過(guò)cond
給出刪除文檔滿(mǎn)足的條件呵扛,比如這個(gè)案例中刪除b=100
的文檔。justOne
是可選參數(shù)筐带,boolean類(lèi)型今穿,表示是否僅刪除滿(mǎn)足條件的一個(gè)文檔還是所有文檔,默認(rèn)刪除所有文檔伦籍,如果只刪除一個(gè)蓝晒,則標(biāo)記為1
或true
。
> cond = {'b': 100};
> db.<coll_name>.remove(cond,1); # 僅刪除一個(gè)滿(mǎn)足條件的數(shù)據(jù)帖鸦,不加`1`則刪除所有滿(mǎn)足條件的數(shù)據(jù)
WriteResult({ "nRemoved" : 1}
(2022.08.30 Tues)
更新
mongodb的數(shù)據(jù)更新使用update
命令芝薇。更新的格式為
db.<coll_name>.update(<query>, <update>, {upsert: <boolean>,
multi: <boolean>, writeConcern: <document>})
格式中的<query>
代表查詢(xún)條件,如對(duì)b=103
的所有記錄做修改作儿,則{b: 103}
洛二。
<update>
代表更新操作,共分為六種
-
$set
:設(shè)定某字段為新值 -
$inc
:設(shè)定字段值的自增/減量 -
$unset
:刪除指定的字段 -
$push
:在數(shù)組的結(jié)尾加入一個(gè)元素/數(shù)組,格式為$push: {<list_name>: [xxx]}
晾嘶,push數(shù)組則添加數(shù)組妓雾,push元素則添加元素 -
$pull
:從數(shù)組中刪除元素,如果有多個(gè)滿(mǎn)足條件的垒迂,則全部刪除 -
$pop
:從數(shù)組的結(jié)尾或開(kāi)頭刪除一個(gè)元素械姻,通過(guò)設(shè)置標(biāo)志位指定是從結(jié)尾刪還是開(kāi)頭刪,1
結(jié)尾0
開(kāi)頭机断,格式為$pop: {<list_name>: 1}
后面是可選參數(shù)楷拳,共三個(gè)
-
$upsert
:如果不存在update的記錄,是否插入新對(duì)象毫缆,true為插入唯竹,默認(rèn)是false,不插入苦丁,即update+insert
浸颓。 -
$multi
:是否更新多條滿(mǎn)足條件的記錄,默認(rèn)false即只更新一條滿(mǎn)足條件的記錄旺拉,參數(shù)為true則更新全部滿(mǎn)足條件的記錄产上。 -
$writeConcern
:拋出異常級(jí)別
更新的命令案例
> db.<coll_name>.update({b: 3}, {$set:{'age': 26}}, {multi: true})
> db.<coll_name>.update({b: 105, test: 100}, {$inc: {age: 10}}, true, true); # 結(jié)尾的兩個(gè)true,分別表示為如果沒(méi)有該對(duì)象則插入蛾狗,和所有符合條件的記錄都執(zhí)行該操作晋涣;該案例中沒(méi)有`b:105`這個(gè)對(duì)象,所以執(zhí)行insert
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("630d90f0529d851b78334af0")
})
ObjectID對(duì)象
(2022.09.23 Fri)
在mongoDB中使用ObjectId()
命令可以生成一個(gè)12字節(jié)(byte)的ObjectId對(duì)象沉桌。上面的案例中谢鹊,每個(gè)記錄都對(duì)應(yīng)了一個(gè)獨(dú)一無(wú)二的_id
,比如ObjectId("630d90f0529d851b78334af0")
(共24位16進(jìn)制數(shù))留凭,其中包括
- 4字節(jié)時(shí)間戳(timestamp)佃扼,是ObjectId的創(chuàng)建時(shí)間,以Unix epoch的秒數(shù)度量蔼夜,即前4位
- 5字節(jié)的隨機(jī)值兼耀,該值對(duì)機(jī)器和進(jìn)程來(lái)說(shuō)獨(dú)一無(wú)二
- 3字節(jié)增量計(jì)數(shù)器(incrementing counter),初始值隨機(jī)求冷,即后6位
ObjectId的內(nèi)置方法包括下面幾種
- ObjectId().getTimestamp():返回ObjectId中時(shí)間的部分瘤运,以ISO形式,如
> ObjectId("632c0e025cc2e01646951254").getTimestamp()
ISODate("2022-09-22T07:25:54Z")
- ObjectId().toString():返回JavaScript表達(dá)匠题,以string形式
ObjectId(...)
> ObjectId("632c0e025cc2e01646951254").toString()
ObjectId("632c0e025cc2e01646951254")
- ObjectID.valueOf():返回ObjectId的16進(jìn)制字符表達(dá)(hexadecimal)拯坟,返回字符
> ObjectId("632c0e025cc2e01646951254").valueOf()
632c0e025cc2e01646951254
Reference
1 mongodb 官方文檔
2 mongodb 百度百科
3 NoSQL DB 系列解讀:一文看懂 MongoDB,微信公眾號(hào)TWT企業(yè)IT社區(qū)