背景
最近客戶端項(xiàng)目數(shù)據(jù)庫(kù)替換成PouchDB(v7.2.2),在轉(zhuǎn)移分頁功能時(shí)遇到了問題井仰。
場(chǎng)景
考慮性能和拓展空間破加,采用 db.allDocs()
作為批量查詢方法俱恶,用skip
和limit
參數(shù)實(shí)現(xiàn)分頁速那,例如:
let skipNum = 0;
db.allDocs({
limit: 50, // page size
skip: skipNum,
}).then(res => {
const { rows } = res;
......
skipNum += rows.length; // skip loaded data
});
});
首頁加載異常尿背,檢查返回的rows
里包含了創(chuàng)建的索引
,原來是在之前測(cè)試時(shí)無意中創(chuàng)建了索引(db.createIndex()
)捶惜,索引
的_id
以_design/idx-
開頭田藐,查詢得知db.allDocs()
方法會(huì)返回?cái)?shù)據(jù)庫(kù)所有數(shù)據(jù),且索引
也存儲(chǔ)在業(yè)務(wù)數(shù)據(jù)”表“中吱七,這就導(dǎo)致返回?cái)?shù)據(jù)包含了`索引汽久,不是期望的結(jié)果。
個(gè)人覺得
索引
這種業(yè)務(wù)無關(guān)數(shù)據(jù)不應(yīng)該放入這張"表"踊餐,違反直覺
那么刪除索引景醇,此時(shí)返回如預(yù)期一樣,返回業(yè)務(wù)數(shù)據(jù)吝岭,并且最大數(shù)據(jù)按照limit
限制來返回三痰。
如果搜索必須依賴索引,而索引與業(yè)務(wù)數(shù)據(jù)同一個(gè)數(shù)據(jù)庫(kù)窜管,怎么辦呢散劫?
這個(gè)數(shù)據(jù)庫(kù)有另一個(gè)跟直覺相悖的地方,假定搜索字段必須要?jiǎng)?chuàng)建索引
才能實(shí)現(xiàn)幕帆,這次使用db.find()
來使用索引
获搏。
let skipNum = 0;
// db內(nèi)假定是如此[1,2,3,4,5],5條業(yè)務(wù)數(shù)據(jù)
db.createIndex({
index: {fields: ['_id']} // 對(duì)內(nèi)部屬性建立索引
}).then(function () {
/*
創(chuàng)建索引后失乾,db內(nèi)數(shù)據(jù)條數(shù)已經(jīng)是6常熙, 使用db.info()和db.allDocs()獲取數(shù)據(jù)長(zhǎng)度皆為6纬乍。
但是db.find()獲取的長(zhǎng)度還是5,看來已經(jīng)過濾掉索引數(shù)據(jù)裸卫,很棒蕾额。
**/
return db.find({
selector: {_id: {$gt: null}},
limit: 50, // page size
skip: skipNum,
}).then(res => {
const { docs } = res.docs;
......
skipNum += docs.length; // skip loaded data
/*
dosc.length等于5,
所以加載下一頁時(shí)彼城,skipNum等于5诅蝶,跳過5條,應(yīng)該返回docs等于[]才是預(yù)期募壕,可實(shí)際上调炬?
**/
});
});
實(shí)際上返回一個(gè)包含一條數(shù)據(jù)的數(shù)組。猜想在skip
時(shí)舱馅,db.find()
方法還是把索引計(jì)入了缰泡。這就是上文返回重復(fù)的根本原因。
這非常讓人迷惑代嗤,返回?cái)?shù)據(jù)不含索引棘钞,但是
skip
跳過數(shù)據(jù)又計(jì)算了索引
。
結(jié)論
不使用索引或者只需要搜索內(nèi)部屬性_id
的干毅,不需要db.createIndex()
宜猜,這樣即使需要分頁使用skip
也沒有影響。
需要索引硝逢,且需要分頁的姨拥,db.find()
不會(huì)返回索引
數(shù)據(jù)到結(jié)果中,但是注意skip
渠鸽,在計(jì)算跳過的時(shí)候會(huì)計(jì)入索引
叫乌,在編寫代碼時(shí)如果遇到重復(fù)數(shù)據(jù),需要留意了徽缚。