如何使用 Ionic Infinite Scroll 对 PouchDB 进行分页?

How to do pagination with PouchDB using Ionic Infinite Scroll?

假设我有 100 个文档(注意:文档总数肯定会增加)。一次获取所有 100 个文档会导致性能问题,所以我认为我需要进行无限滚动和显示,比方说,第一次加载时有 15 个文档。每次触发无限滚动,它应该再得到 15 个文档。

基本上,docArr.length = 100

首次加载:抓取 docArr[0]docArr[14]

触发无限卷轴:抓取docArr[15]docArr[29]等直到docArr[99]也被抓取

PouchDB FAQ on Pagination中说明需要使用startkeyendkeylimitskip

我的文档 ID 的格式为 doc-1。所以我有 doc-1doc-2doc-3

我按照建议的方法使用,所以我的代码是;

var options = {limit : 15};
function fetchNextPage() {
  pouch.allDocs(options, function (err, response) {
    if (response && response.rows.length > 0) {
      let id_num = response[response.length - 1]._id.split('-').pop()
      //on first trigger, the line above should get '15'

      id_num = Number(id_num) + 1
      let id = 'doc-' + id_num 
      //on first trigger, id = 'doc-16'
      options.startkey = id;
      options.skip = 1;
    }
    // handle err or response
    
  });
}

但是,当我这样做时,当我触发无限滚动时,即使我增加了 id(这我用作 startkey).

如何在每次触发无限滚动(进行分页)时获取接下来的 15 个文档?

我不是 100% 清楚 OP 的代码是怎么回事,但是假设 _all_docs 的第一个查询的 response.rows 是有序的所以

rows index id
0 doc-1
1 doc-2
2 doc-3
3 doc-4
4 doc-5
5 doc-6
6 doc-7
7 doc-8
8 doc-9
9 doc-10
10 doc-11
11 doc-12
12 doc-13
13 doc-14
14 doc-15

错误的。文档 ID 是字符串,因此遵循 CouchDB 文档 3.2.2.5. Collation Specification.

中记录的整理规则

根据 OP 指定的文档 ID 格式,这应该是 实际 文档 ID 序列,由对 _all_docs 的初始调用返回:

rows index id
0 doc-1
1 doc-10
2 doc-100
3 doc-11
4 doc-12
5 doc-13
6 doc-14
7 doc-15
8 doc-16
9 doc-17
10 doc-18
11 doc-19
12 doc-2
13 doc-20
14 doc-21

因此下一组结果的计算是有缺陷的

id_num = Number(id_num) + 1
let id = 'doc-' + id_num   
options.startkey = id;

计算下一个 id 是个坏主意,完全没有必要。而是使用 最后一个文档的 ID,例如

    let result = await db.allDocs(options);        
    if(result.rows.length) {
      // do something with results
      // get next page of docs?
      if(result.rows.length === options.limit) {        
        options.startkey = result.rows.pop().id;
        options.skip = 1;
        // repeat 
      }
    }

此代码段使用setTimeout每秒抓取15个文档,将文档id记录到控制台,当返回的文档数量小于limit时退出,表示结束结果。

// canned test documents
function getDocsToInstall() {
  let docs = [];
  for (let i = 1; i < 101; i++) {
    docs.push({
      _id: `doc-${i}`
    });
  }
  return docs;
}

let db;

// init db instance
async function initDb() {
  db = new PouchDB('test', {
    adapter: 'memory'
  });
  await db.bulkDocs(getDocsToInstall());
}

function update(result) {
  console.log(result.rows.map(d => d.id).join(','));
}

initDb().then(async() => {
  let options = {
    limit: 15,
    include_docs: false,
    reduce: false
  };
  async function timerFn() {
    let result = await db.allDocs(options);
    if (result.rows.length) {
      update(result);
      // get next page of docs
      if (result.rows.length === options.limit) {
        options.startkey = result.rows.pop().id;
        options.skip = 1;
        // repeat
        setTimeout(timerFn, 1000);
      } else {
        console.log("All docs processed ");
      }
    }
  };
  timerFn();
});
<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>