[英]Pagination in CouchDB?
我將如何實現分頁所需的查詢?
基本上,當請求第1頁時,獲取前5個條目。 對於第2頁,獲取下一個5,依此類推。
我計划通過couchdb-python模塊使用它,但這不會對實現產生任何影響。
CouchDB指南對分頁進行了很好的討論,包括大量示例代碼,這里是: http : //guide.couchdb.org/draft/recipes.html#pagination這是他們的算法:
rows_per_page + 1
行 rows_per_page
行,將最后一行存儲為next_startkey
startkey
和next_startkey
next_*
值創建下一個鏈接,並使用其他鏈接創建上一個鏈接 注意:在CouchDB中獲取頁面的正確方法是指定一個起始鍵,而不是你想象的起始索引。 但是你怎么知道開始第2頁的關鍵是什么? 聰明的解決方案:“不是為頁面請求10行,而是請求11行,但只顯示10行,並使用第11行中的值作為下一頁的開始鍵。”
如果你希望有多個文件發出相同的密鑰,你需要使用startdocid
除了startkey
正確分頁。 原因是單獨的startkey
將不再足以唯一地標識行。 如果您不提供startkey
那些參數將無用。 事實上,CouchDB將首先查看startkey
參數,然后如果多個潛在的凝視行具有相同的密鑰但文檔ID不同,它將使用startdocid
參數進一步重新定義范圍的開頭。 enddocid
也是enddocid
。
CouchDB HTTP View API提供了足夠的范圍來有效地進行分頁。
最簡單的方法是使用startkey
和count
。 Count是CouchDB將為該視圖請求返回的最大條目數,這取決於您的設計,startkey是您希望CouchDB啟動的位置。 當您請求視圖時,它還會告訴您有多少條目,允許您計算如果要向用戶顯示該條目的頁數。
因此,第一個請求不會指定啟動鍵,只會指定要顯示的條目數。 然后,您可以記下返回的最后一個條目的鍵,並將其用作下一頁的開始鍵。 在這個簡單的表單中,您將獲得重疊,其中一個頁面的最后一個條目是下一個頁面的第一個條目。 如果這不可取,那么簡單地不顯示頁面的最后一個條目是微不足道的。
更簡單的方法是使用skip參數計算頁面的起始文檔,但是應謹慎使用此方法。 skip參數只是導致內部引擎不返回它正在迭代的條目。 雖然這給出了期望的行為,但它比按鍵查找頁面的第一個文檔慢得多。 跳過的文檔越多,請求就越慢。
這就是我到目前為止所提出的 - 獲取所有帖子的ID,然后檢索前x個ID的實際項目。
這不是非常有效,但比檢索所有帖子更重要,然后扔掉大部分。 這就是說,令我驚訝的是,它似乎運行得很快 - 我運行了posthelper.page()
方法100次,大約需要0.5秒。
我不想在實際問題中發布這個,所以它不會影響答案 - 這是代碼:
allPostsUuid = """
function(doc) {
if(doc.type == 'post'){
emit(doc._id, null);
}
}
"""
class PostsHelper:
def __init__(self):
server = Server(config.dbhost)
db = server[config.dbname]
return db
def _getPostByUuid(self, uuid):
return self.db.get(uuid)
def page(self, number = 1):
number -= 1 # start at zero offset
start = number * config.perPage
end = start + config.perPage
allUuids = [
x.key for x in self.db.query(allPostsUuid)
]
ret = [
self._getPostByUuid(x) for x in allUuids[start : end]
]
if len(ret) == 0:
raise Error404("Invalid page (%s results)" % (len(allUuids)))
else:
return ret
下面是我發現的遞歸方式:
拿兩個變量
var lastOffset = 0; var counter = 0;
function someRecursive(lastOffset,counter) {
queryView(db, whereClause).then(result => {
var rows_per_page = 5;
//formula below
var page = Math.floor((lastOffset == 0 ? 0: (result.offset - lastOffset) +
(rows_per_page * counter)) / rows_per_page) + 1;
var skip = page * rows_per_page;
if (somerecursionexitcondition) {
counter = lastOffset == 0 ? lastOffset: counter + 1;
lastOffset =result.offset;
someRecursive(lastOffset, counter).then(result => {
resolve();
});
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.