作為近年最為火熱的文檔型數(shù)據(jù)庫,MongoDB受到了越來越多人的關(guān)注,但是由于國內(nèi)的MongoDB相關(guān)技術(shù)分享屈指可數(shù),不少朋友向我抱怨無從下手。
創(chuàng)新互聯(lián)建站為企業(yè)級客戶提高一站式互聯(lián)網(wǎng)+設(shè)計服務(wù),主要包括成都做網(wǎng)站、成都網(wǎng)站設(shè)計、重慶App定制開發(fā)、微信平臺小程序開發(fā)、宣傳片制作、LOGO設(shè)計等,幫助客戶快速提升營銷能力和企業(yè)形象,創(chuàng)新互聯(lián)各部門都有經(jīng)驗豐富的經(jīng)驗,可以確保每一個作品的質(zhì)量和創(chuàng)作周期,同時每年都有很多新員工加入,為我們帶來大量新的創(chuàng)意。
《MongoDB干貨系列》將從實際應(yīng)用的角度來進行MongoDB的一些列干貨的分享,將覆蓋調(diào)優(yōu),troubleshooting等方面,希望能對大家?guī)韼椭?/p>
如果希望了解更多MongoDB基礎(chǔ)的信息,還請大家Google下。
我們知道MongoDB是一個文檔型數(shù)據(jù)庫,scheme free 是其非常重要的特性,但是在生產(chǎn)中我們應(yīng)該怎么如合理利用這個特性,合理處理MongoDB的schema呢?
大家都知道MongoDB是文檔型數(shù)據(jù)庫,是Schema Free的。
那么MongoDB的文檔模型能給我們帶來哪些好處呢,在這簡單列舉幾個:
在這,我們不深入探究如何對于MongoDB 的Schema進行設(shè)計、建模,有關(guān)這部分內(nèi)容,推薦大家可以閱讀TJ在開源中國的年終盛典會上分享《MongoDB 進階模式設(shè)計》,以及《Retail Reference Architecture Part 1 to 4 》。
在此我們將主要針對進行了初步建模、并正式上線服務(wù)后的schema進行巡檢與檢測的方式來進行討論。
Variety是一個開源的,非常使用的,檢測mongodb表字段類型、分布的一個開源工具。
正如其github readme中第一句所說”Meet Variety, a Schema Analyzer for MongoDB”
Variety能夠幫助我們檢測我們MongoDB表中的字段類型、分布,并生產(chǎn)報表,可以讓我們非常直觀的對現(xiàn)有表結(jié)構(gòu)、字段類型進行分析,并找出數(shù)據(jù)模型中的隱患。
首先,建立一個表
db.users.insert({name: "Tom", bio: "A nice guy.", pets: ["monkey", "fish"], someWeirdLegacyKey: "I like Ike!"}); db.users.insert({name: "Dick", bio: "I swordfight.", birthday: new Date("1974/03/14")}); db.users.insert({name: "Harry", pets: "egret", birthday: new Date("1984/03/14")}); db.users.insert({name: "Geneviève", bio: "?a va?"}); db.users.insert({name: "Jim", someBinData: new BinData(2,"1234")});
我們來看看通過variety獲得的結(jié)果
$ mongo test --eval "var collection = 'users'" variety.js +------------------------------------------------------------------+ | key | types | occurrences | percents | | ------------------ | ------------ | ----------- | -------- | | _id | ObjectId | 5 | 100.0 | | name | String | 5 | 100.0 | | bio | String | 3 | 60.0 | | birthday | String | 2 | 40.0 | | pets | Array(4),String(1) | 5 | 40.0 | | someBinData | BinData-old | 1 | 20.0 | | someWeirdLegacyKey | String | 1 | 20.0 | +------------------------------------------------------------------+
test是我們的db名,users是表名。我們可以看到,針對我們之前插入的5條數(shù)據(jù),variety跑出的結(jié)果是:
所有的document都含有_id,和name字段,60%的document含有bio字段,40%的document含有birthday和pets字段,且pets字段有2個類型的數(shù)據(jù)(4個array的,1個string的),20%的document含有someBinData和SomeWeirdLegacyKey字段。
然而生產(chǎn)環(huán)境中由于我們的數(shù)據(jù)量較大,比如一個表有10億條數(shù)據(jù),全部進行掃描會耗時較長,可能我們僅希望對1000條數(shù)據(jù)進行分析,這時候就可以使用limit來限定。
$ mongo test --eval "var collection = 'users', limit = 1000" variety.js +----------------------------------------------------+ | key | types | occurrences | percents | | ----------- | ----------- | ----------- | -------- | | _id | ObjectId | 1000 | 100.0 | | name | String | 1000 | 100.0 | | someBinData | BinData-old | 1000 | 100.0 | +----------------------------------------------------+
由于MongoDB的可以通過內(nèi)嵌來減少聯(lián)合查詢的需求,可以通過反范式來減少隨機IO,所以很可能會有嵌套出現(xiàn)在我們的document中。有的時候嵌套的層數(shù)太多了,影響我們的統(tǒng)計信息,怎么辦,我們可以通過maxDepth來限制。請參考下面的例子:
db.users.insert({name:"Walter", someNestedObject:{a:{b:{c:{d:{e:1}}}}}}); $ mongo test --eval "var collection = 'users'" variety.js +----------------------------------------------------------------+ | key | types | occurrences | percents | | -------------------------- | -------- | ----------- | -------- | | _id | ObjectId | 1 | 100.0 | | name | String | 1 | 100.0 | | someNestedObject | Object | 1 | 100.0 | | someNestedObject.a | Object | 1 | 100.0 | | someNestedObject.a.b | Object | 1 | 100.0 | | someNestedObject.a.b.c | Object | 1 | 100.0 | | someNestedObject.a.b.c.d | Object | 1 | 100.0 | | someNestedObject.a.b.c.d.e | Number | 1 | 100.0 | +----------------------------------------------------------------+ $ mongo test --eval "var collection = 'users', maxDepth = 3" variety.js +----------------------------------------------------------+ | key | types | occurrences | percents | | -------------------- | -------- | ----------- | -------- | | _id | ObjectId | 1 | 100.0 | | name | String | 1 | 100.0 | | someNestedObject | Object | 1 | 100.0 | | someNestedObject.a | Object | 1 | 100.0 | | someNestedObject.a.b | Object | 1 | 100.0 | +----------------------------------------------------------+
又或者我們希望指定統(tǒng)計的條件,比如希望caredAbout為true的,可以這樣做:
$ mongo test --eval "var collection = 'users', query = {'caredAbout':true}" variety.js
又或者是希望進行排序:
$ mongo test --eval "var collection = 'users', sort = { updated_at : -1 }" variety.js
同時我們也可以指定分析結(jié)果的format:
$ mongo test --quiet --eval "var collection = 'users', outputFormat='json'" variety.js
一般在生產(chǎn)中, 我們不會在primary上進行分析, 我們可以在一個priority為0,且為hidden的secondary上進行分析,這時候需要指定slaveOK:
$ mongo secondary.replicaset.member:31337/somedb --eval "var collection = 'users', slaveOk = true" variety.js
又或者說我們希望將分析結(jié)果存在mongo中:
$ mongo test --quiet --eval "var collection = 'users', persistResults=true" variety.js
并且指定存儲的詳細(xì)信息:
mongo test --quiet --eval "var collection = 'users', persistResults=true, resultsDatabase='db.example.com/variety' variety.js
盡管我們MongoDB是Schema Free的,但是絕大多數(shù)情況下, 我們都希望字段類型統(tǒng)一。
不一致的字段類型可能會為我們的數(shù)據(jù)帶來誤差,試想一下,如果某個字段的字段類型不統(tǒng)一,而我們卻不知情,這時候很可能會發(fā)現(xiàn)業(yè)務(wù)查詢有數(shù)據(jù)丟失,數(shù)據(jù)不準(zhǔn)確。
并且在生產(chǎn)環(huán)境中,應(yīng)用的版本在不斷迭代,需求不斷增多,字段也隨之變化,如果在沒有規(guī)范化的上線流程檢查過后,數(shù)據(jù)庫中可能還會存在部分?jǐn)?shù)據(jù)的字段確實,比如有的document有a字段,有的卻沒有,variety也可以幫助我們發(fā)現(xiàn)這些問題。
MongoDB 3.2推出了很多給力的功能,在這不得不提及Document Validation,Document Validation的出現(xiàn)我想也是MongoDB官方想表達”schema free but you may need some rules”吧,哈哈,純屬臆測。
簡單介紹下Document Validation:
我們可以為我們schema free的mongodb collection做一些限制。當(dāng)然這并不是意味著MongoDB變成了關(guān)系型數(shù)據(jù)庫,個人覺得這反而更好的突出了MongoDB Schema free的特性。在正確的地方、需要的地方schema free,在適當(dāng)?shù)牡胤揭邢拗啤?
假設(shè)我們要新建一個表contacts,要有如下約束:
phone字段為string類型或者email字段要匹配”@mongodb.com”結(jié)尾,或者status為”Unknown”或者”Incomplete”
db.createCollection( "contacts", { validator: { $or: [ { phone: { $type: "string" } }, { email: { $regex: /@mongodb.com$/ } }, { status: { $in: [ "Unknown", "Incomplete" ] } } ] } } )
對已經(jīng)建立了的表,我們可以通過如下方式來做限定:
db.runCommand( { collMod: "contacts", validator: { $or: [ { phone: { $type: "string" } }, { email: { $regex: /@mongodb.com$/ } }, { status: { $in: [ "Unknown", "Incomplete" ] } } ] }, validationLevel: "moderate" } )
這里可以看到,多了一個validationLevel參數(shù),我們可以在設(shè)置validation的時候指定我們的validationLevel級別:
同時還有validationAction參數(shù)來指定當(dāng)有不符合validation規(guī)則的數(shù)據(jù)進行update或者insert的時候, 我們mongodb實例如何進行處理。
可以設(shè)置為warn,mongodb會在日志中記錄,但是允許這類insert和update操作。日志中如:
2015-10-15T11:20:44.260-0400 W STORAGE [conn3] Document would fail validation collection: example.contacts doc: { _id: ObjectId('561fc44c067a5d85b96274e4'), name: "Amanda", status: "Updated" }
不能對system.*這類collections進行validation設(shè)置;
網(wǎng)站標(biāo)題:【Mongo】MongoDB干貨系列-Variety與DocumentValidation規(guī)范字段
標(biāo)題路徑:http://aaarwkj.com/article46/ipdchg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計公司、軟件開發(fā)、微信公眾號、虛擬主機、外貿(mào)建站、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)