這是我寫出access-db方法庫(kù)所經(jīng)歷的一個(gè)過程,在這里記錄下吧
想法的誕生
小公司的發(fā)展本來就不易箭启,成本方面壕翩,是能有多節(jié)約就多節(jié)約。有時(shí)多個(gè)人干的事轉(zhuǎn)由一個(gè)人干傅寡,也是毫不奇怪
放妈。也是在這種情況下北救,我慢慢的成了全棧開發(fā)。
最初為了省錢芜抒,外加我們只做小程序扭倾,就選擇了第三方云服務(wù)商作為后臺(tái)。剛開始還好挽绩,后面久了膛壹,發(fā)現(xiàn)他們提供的接口方法使用起來并沒有想像的那么輕松。特別是在復(fù)雜查尋的情況下唉堪,代碼太過復(fù)雜模聋,不易讀,修改起來也不方便唠亚。于是我就開始思考怎么去簡(jiǎn)化他的查尋链方。下面這個(gè)查尋方法,就是封裝的最初版灶搜,可以看到祟蚀,fetchFindByCheck
使用起來也并不是那么的簡(jiǎn)單,并且割卖,它還只能支持最簡(jiǎn)單的and
前酿,or
查尋近零,代碼的可讀性和靈活性都不高傻咖。
fetchFindByCheck({
tableName: app.table.active_sign,
relationship: ['and', 'and'],
way: ['in', 'compare', 'compare'],
params: [
{ key: 'child_id', value: childID },
{ key: 'active_id', operator: '=', value: that.aid },
{ key: 'is_delete', operator: '=', value: false },
],
limit: 30,
page: 1,
order_by: '-created_at',
expand: [],
}).then((res2) => {
let tempJoined = res2.data.objects
console.log('tempJoin', tempJoined)
},(err)=>{})
但即使如此,我還是封裝了一套最簡(jiǎn)單的方法空闲。
minapp-fetch 出現(xiàn)
用過云服務(wù)的肯定都知道丙挽,云服務(wù)有很多類別的接口肺孵。就比如微信云開發(fā),它會(huì)提供小程序端的接口颜阐、云函數(shù)的接口平窘、甚至web接口。我們選擇的云服務(wù)商凳怨,剛開始用得還好瑰艘,后面由于業(yè)務(wù)多樣化,我們又面臨不得不使用web的情況猿棉。而且磅叛,云服務(wù)商提供的web接口也和小程序上面的調(diào)用方式不一樣,就導(dǎo)致即使同樣的查尋萨赁,也要寫兩套不同的查尋方法弊琴。如果你還要用他的云函數(shù)、或者其他端的api杖爽,那更是讓你頭大敲董。
怎么辦呢紫皇?為了減輕開發(fā)和維護(hù)難度,提高開發(fā)效率腋寨。我產(chǎn)生了一個(gè)大膽的想法:要是能把各個(gè)端的接口都統(tǒng)一成一種聪铺,那不就很簡(jiǎn)單了嗎。想法是好的萄窜,但實(shí)現(xiàn)起來就沒那么容易了铃剔。最初在寫web端的接口時(shí),我好幾次都想放棄查刻,感覺把這些不同的寫法,統(tǒng)一成一種穗泵,真的是有點(diǎn)難普气。因?yàn)槟悴坏M可能的保證同一種增刪改查,在不同端得到的結(jié)果是一樣的佃延,還要通過算法现诀,保證封裝的方法盡可能的簡(jiǎn)單。
經(jīng)過一段時(shí)間的奮斗履肃,方法終于出來了仔沿,這個(gè)時(shí)候,我給它取了一個(gè)名字榆浓,叫做 minapp-fetch 于未,現(xiàn)在也發(fā)布在了npm上,但它只支持我們使用過的云服務(wù)商的api陡鹃。它的寫法更加簡(jiǎn)潔,如下:
fetchFind(app.table.question, {
p1: {
way: 'compare',
data: ['status', '>', 0]
},
p2: {
way: 'compare',
data: ['is_admin_answered', '=', false]
},
p3: {
way: 'compare',
data: ['is_admin_read', '=', false]
},
r: 'p1 && (p2 || p3)',
page: commen.page,
limit: commen.limit,
order_by: '-created_at',
expand: ['created_by']
})
其中抖坪,p
參數(shù)為每一個(gè)小條件萍鲸,r
為小條件的and、or擦俐,page
為翻頁脊阴,limit
為每頁數(shù)量,order_by
為排序蚯瞧。雖然此時(shí)看著是比較清晰了嘿期,但它還是有不足的地方。首先埋合,p
條件寫法备徐,還是有些繁瑣;其次甚颂,就是r
規(guī)則里面蜜猾,不支持括號(hào)嵌套秀菱;再就是,它支持的方法也不多蹭睡。
面對(duì)上面的種種問題衍菱,當(dāng)然是解決了。經(jīng)過后面的努力肩豁,minapp-fetch才有了現(xiàn)在的寫法:
其中脊串,p
參數(shù)對(duì)應(yīng)的定義是這樣的:p*: ['字段', '查尋方法', '查尋內(nèi)容']
,數(shù)組第一個(gè)參數(shù)為表里的字段清钥,第二個(gè)參數(shù)為查尋方法琼锋,第三個(gè)參數(shù)及后面的,就是查尋的內(nèi)容循捺。
let rule = 'p3 || p7'
minapp.find(table, {
p1: ['cat_label1', 'in', userChannels=[]],
p2: ['cat_label2', 'stringLength', 23], //查尋字符串長(zhǎng)度為23的
p4: ['cat_label2', 'stringLength', 23, 100], //查尋字符串長(zhǎng)度在23到100的
p3: ['id', 'notIn', history],
p7: ['status', '=', 20],
p8: ['name', 'matches', /^foo/i],
p15: ['geo_point', 'include', [15, 15]], //坐標(biāo)點(diǎn)斩例,經(jīng)緯[longitude, latitude]
p21: ['geo_point', 'withinCircle', [15, 15], r], //r 單位 km
p23: ['geo_point', 'withinRegion', [15, 15], max_r], //max_r, min_r 單位為 m
p28: ['geo_point', 'within', [0, 0], [6, 0], [6, 9], [0, 9], [0, 0]], //坐標(biāo)點(diǎn)集,首點(diǎn)=尾點(diǎn)从橘,經(jīng)緯[longitude, latitude]
p63: ['content', 'isNull', true],
p93: ['content', 'isExists', false],
r: isSelect ? rule : '(p1 && (p2 || p3)) && (p57 && p93)',
page: 1, //默認(rèn)值
limit: 20, //默認(rèn)值
orderBy: '-created_at', //默認(rèn)值
expand: [], //默認(rèn)值
select: [], //默認(rèn)值
withCount: false, //默認(rèn)值
})
可以看到念赶,上面的find方法,已經(jīng)相當(dāng)復(fù)雜了恰力,但它給人的感覺叉谜,還是很清。你甚至可以隨意更換r規(guī)則
踩萎,進(jìn)行不同情況的查尋停局。(查尋最終是按r規(guī)則
來的)
access-db 出現(xiàn)
再后來,由于云服務(wù)商的一些不足香府,外加我們自己也對(duì)業(yè)務(wù)靈活性有更多要求董栽,所以決定自己寫后臺(tái)了。慢慢的企孩,我們逐漸開始放棄云服務(wù)商锭碳,自己開發(fā)。此時(shí)問題也來了勿璃,數(shù)據(jù)庫(kù)的連接各不相同擒抛,習(xí)慣了minapp-fetch寫法的我,再去單獨(dú)用數(shù)據(jù)庫(kù)的連接方法补疑,感覺確實(shí)不習(xí)慣歧沪。并且,不同類型的數(shù)據(jù)庫(kù)莲组,方法也不一樣诊胞,維護(hù)和轉(zhuǎn)化,成了一大難題胁编。你肯定也猜到了厢钧,沒錯(cuò)鳞尔,就是把數(shù)據(jù)庫(kù)的連接,也封裝起來早直!
從node.js最火的非關(guān)系型數(shù)據(jù)庫(kù)mongodb
入手寥假,開始了數(shù)據(jù)庫(kù)方法封裝的旅程。說實(shí)在的霞扬,mongodb
的基本方法和之前云服務(wù)商的webapi很相似糕韧,也沒費(fèi)太多的功夫就完成了常用方法的封裝。但后面加入第二個(gè)數(shù)據(jù)庫(kù)mysql
時(shí)喻圃,問題就來了萤彩。因?yàn)?code>mysql是sql語句
進(jìn)行查尋的,和之前的完全不一樣斧拍。也就是說雀扶,必須要通過算法,將封裝的寫法肆汹,轉(zhuǎn)換成sql語句愚墓。你可能會(huì)覺得,應(yīng)該不復(fù)雜昂勉,就是一個(gè)簡(jiǎn)單的組成字符串而已浪册。當(dāng)初我也是這么認(rèn)為的,但當(dāng)我開始入手研發(fā)時(shí)岗照,才發(fā)現(xiàn)村象,問題遠(yuǎn)比這個(gè)復(fù)雜。對(duì)mysql了解的同學(xué)應(yīng)該知道攒至,sql語句可以重命名厚者、可以連表查尋、可以嵌套查詢迫吐、聚合查尋等籍救,并且為了使查尋正確,往往還要對(duì)表和字段進(jìn)行更名渠抹,再引用等等,這些問題就使得轉(zhuǎn)化難度大大提高了闪萄∥嗳矗可能有時(shí)候,你滿足了其中一種查尋败去,卻讓另一種查尋出了問題放航。但為了平時(shí)開發(fā)得更爽,更高效圆裕;我還是硬著頭皮去實(shí)現(xiàn)它广鳍。
經(jīng)過一段時(shí)間的苦熬荆几,她終于開始有個(gè)樣子了,我又重新發(fā)了一個(gè)npm包赊时,給了她一個(gè)全新的名字:access-db吨铸,至此,你甚至可以同時(shí)引用多種數(shù)據(jù)庫(kù)祖秒,進(jìn)行關(guān)聯(lián)使用:
import {mysql, mongodb, fastdb} from 'access-db'
async function exp() {
let {data} = await mongodb.get('table11', id)
await mysql.find('table2', {
p0: ['num', '=', data.num],
r: 'p0'
})
}
因?yàn)槊恳环N數(shù)據(jù)庫(kù)诞吱,都有自己的特點(diǎn),所以竭缝,封裝的方法里面房维,肯定會(huì)有個(gè)體差異,這也無法避免抬纸。
Fastdb 出現(xiàn)
細(xì)心的同學(xué)可能發(fā)現(xiàn)了上面的代碼中咙俩,引入了一種新的數(shù)據(jù)庫(kù)fastdb
,是的湿故,它是access-db
內(nèi)置的阿趁,本地json數(shù)據(jù)庫(kù)。也是我發(fā)現(xiàn)有類似的本地?cái)?shù)據(jù)庫(kù)后晓锻,自己開發(fā)的歌焦。它的優(yōu)點(diǎn)就是,完全使用access-db
語法進(jìn)行增刪改查砚哆,同時(shí)独撇,不需要你安裝任何額外數(shù)據(jù)庫(kù),直接可以用躁锁,很方便纷铣。缺點(diǎn)也很明顯,存儲(chǔ)的形式是json文件战转,沒有數(shù)據(jù)庫(kù)密碼這些搜立,不安全,數(shù)據(jù)量大了槐秧,查尋效率也不是那么高啄踊。
結(jié)語
我希望通過記錄自己的這些經(jīng)歷,能帶給你些啟發(fā)或共鳴刁标。我不是什么大神颠通,可能你也不是,但只要自己不停下思考的腳步膀懈,并勇于去實(shí)現(xiàn)它顿锰,那你也一定能做出有意義東西出來!
將這個(gè)方法庫(kù),獻(xiàn)給那些需要的朋友:
access-db包
access-db文檔