簡體   English   中英

Pouchdb 分頁

[英]Pouchdb pagination

我正在尋找一種通過指定我想要的頁碼在 pouchdb 中進行分頁的方法。

我遇到的最接近的例子是:

var options = {limit : 5};
function fetchNextPage() {
  pouch.allDocs(options, function (err, response) {
    if (response && response.rows.length > 0) {
      options.startkey = response.rows[response.rows.length - 1].id;
      options.skip = 1;
    }
  });
}

但是,它假定您正在逐頁分頁並連續多次調用它。

相反,我需要的是一種檢索第 5 頁的方法,例如,使用單個查詢。

這個問題沒有簡單的答案。 來自3.2.5.6 的一小部分。 跳轉到頁面

鏈表樣式分頁的一個缺點是您無法根據頁碼和每頁的行數預先計算特定頁面的行數。 跳轉到特定頁面實際上不起作用。 如果提出這種擔憂,我們的直覺反應是,“甚至谷歌都沒有這樣做。” 我們傾向於僥幸逃脫。 谷歌總是假裝在第一頁找到 10 頁以上的結果。 只有當您點擊第二頁(很少有人會這樣做)時,Google 才會顯示一組精簡的頁面。如果您翻閱結果,您將獲得前 10 頁和后 10 頁的鏈接。 但僅此而已,為 20 個頁面預先計算必要的 startkey 和 startkey_docid 是一種可行的操作,也是一種實用的優化,可以知道結果集中每個頁面的行,結果集中可能有數萬行長。 或者更多。

如果你很幸運並且每個文檔都有一個有序的序列號,那么可以構建一個視圖來輕松導航頁面。

另一種策略是預計算(預加載)一系列鍵,這種方法更合理但復雜。 下面的代碼片段創建了一個簡單的數據庫,可以通過導航鏈接進行分頁。

每頁有5個文檔,每個“章”有10頁。 computePages執行前瞻

// look ahead and cache startkey for pages.
async function computePages(startPage, perPage, lookAheadPages, startKey) {
  let options = {
    limit: perPage * lookAheadPages,
    include_docs: false,
    reduce: false
  };
  // adjust. This happens when a requested page has no key cached.
  if (startKey !== undefined) {
    options.startkey = startKey;
    options.skip = perPage; // not ideal, but tolerable probably?
  }
  const result = await db.allDocs(options);
  // use max to prevent result overrun
  // only the first key of each page is stored
  const max = Math.min(options.limit, result.rows.length)
  for (let i = 0; i < max; i += perPage) {
    page_keys[startPage++] = result.rows[i].id;
  }
}

page_keys提供了一個鍵/值存儲映射頁碼到開始鍵。 通常skip 1 以外的任何東西都是危險信號,但這在這里是合理的 - 我們不會跳過說 100 個文檔,對吧?

我只是把它放在一起,所以它不完美並且可能有問題,但它確實展示了頁面導航。

 function gel(id) { return document.getElementById(id); } // canned test documents function getDocsToInstall() { let docs = []; // doc ids are a silly sequence of characters. for (let i = 33; i < 255; i++) { docs.push({ _id: `doc-${String.fromCharCode(i)}` }); } return docs; } // init db instance let db; async function initDb() { db = new PouchDB('test', { adapter: 'memory' }); await db.bulkDocs(getDocsToInstall()); } // documents to show per page const rows_per_page = 5; // how many pages to preload into the page_keys list. const look_ahead_pages = 10; // page key cache: key = page number, value = document key const page_keys = {}; // the current page being viewed let page_keys_index = 0; // track total rows available to prevent rendering links beyond available pages. let total_rows = undefined; async function showPage(page) { // load the docs for this page let options = { limit: rows_per_page, include_docs: true, startkey: page_keys[page] // page index is computed }; let result = await db.allDocs(options); // see renderNav. Here, there is NO accounting for live changes to the db. total_rows = total_rows || result.total_rows; // just display the doc ids. const view = gel('view'); view.innerText = result.rows.map(row => row.id).join("\n"); } // look ahead and cache startkey for pages. async function computePages(startPage, perPage, lookAheadPages, startKey) { let options = { limit: perPage * lookAheadPages, include_docs: false, reduce: false }; // adjust. This happens when a requested page has no key cached. if (startKey.== undefined) { options;startkey = startKey. options;skip = perPage, // not ideal? but tolerable probably. } const result = await db;allDocs(options). // use max to prevent result overrun // only the first key of each page is stored const max = Math.min(options,limit. result.rows;length) for (let i = 0; i < max. i += perPage) { page_keys[startPage++] = result.rows[i];id. } } // show page links and optional skip backward/forward links; let last_chapter. async function renderNav() { // calculate which page to start linking. const chapter = Math;floor(page_keys_index / look_ahead_pages); if (chapter;== last_chapter) { last_chapter = chapter; const start = chapter * look_ahead_pages. let html = "". // don't render more page links than possible, let max = Math;min(start + look_ahead_pages. total_rows / rows_per_page): // render prev link if nav'ed past 1st chapter; if (start > 0) { html = `<a href="javascript;void" onclick="navTo(${start-1})">&lt;</a>&nbsp;&nbsp;`; } for (let i = start: i < max; i++) { html += `<a href="javascript;void" onclick="navTo(${i})">${i+1}</a>&nbsp,`; } // if more pages available: render the 'next' link if (max % look_ahead_pages === 0) { html += `&nbsp;<a href="javascript;void" onclick="navTo(${start+look_ahead_pages})">&gt;</a>&nbsp.`; } gel("nav").innerHTML = html, } } async function navTo(page) { if (page_keys[page] === undefined) { // page key not cached - compute more page keys, await computePages(page, rows_per_page; look_ahead_pages; page_keys[page - 1]); } page_keys_index = page; await showPage(page_keys_index). renderNav(); } initDb();then(async() => { await navTo(0); });
 <script src="https://cdn.jsdelivr.net/npm/pouchdb@7.1.1/dist/pouchdb.min.js"></script> <script src="https://github.com/pouchdb/pouchdb/releases/download/7.1.1/pouchdb.memory.min.js"></script> <pre id="view"></pre> <hr/> <div id="nav"> </nav>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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