簡體   English   中英

CouchDB中的分頁?

[英]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
  • 作為頁面信息,請保持startkeynext_startkey
  • 使用next_*值創建下一個鏈接,並使用其他鏈接創建上一個鏈接

注意:在CouchDB中獲取頁面的正確方法是指定一個起始鍵,而不是你想象的起始索引。 但是你怎么知道開始第2頁的關鍵是什么? 聰明的解決方案:“不是為頁面請求10行,而是請求11行,但只顯示10行,並使用第11行中的值作為下一頁的開始鍵。”

如果你希望有多個文件發出相同的密鑰,你需要使用startdocid除了startkey正確分頁。 原因是單獨的startkey將不再足以唯一地標識行。 如果您不提供startkey那些參數將無用。 事實上,CouchDB將首先查看startkey參數,然后如果多個潛在的凝視行具有相同的密鑰但文檔ID不同,它將使用startdocid參數進一步重新定義范圍的開頭。 enddocid也是enddocid

CouchDB HTTP View API提供了足夠的范圍來有效地進行分頁。

最簡單的方法是使用startkeycount 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM