按 unix 时间戳和分页对 CouchDB 结果进行排序

Sorting CouchDB result by unix timestamp and paginate

这几天我一直在努力让分页工作。我有一个带有文档的数据库,并且有一些数据库将时间戳作为降序排序的关键。但我似乎无法获得下一组文档...

如果我 运行 它,我将获得前 5 个文档。当我尝试使用 startkey 或 startkey_docid 时,我似乎只会再次获得相同的行。

尝试沙发文档我不确定我需要什么才能让它工作。

couchdb 的设计如下:

{
  "_id": "_design/filters",
  "views": {
    "blog": {
      "map": "function (doc) { if (doc.published && doc.type == 'post') emit(doc.header.date); }"
    }
  }
}

... header.date+new Date()

生成

在nodejs端,使用github/nano,我使用类似于:

import nano from 'nano';

let db = nano(SERVICE_URL).use('blog_main');

let lastDocId = ctx.query.lastDocId;
let lastSkip = ctx.query.lastSkip ? +ctx.query.lastSkip + 5 : null;

let query = {
    limit: 1 + 4,       // limit to 5
    descending: true,   // reverse order: newest to top
    include_docs: true,
}
if (lastDocId) { // initally off
    query.startkey = lastDocId;
}
if (lastSkip) { // other method for tests
    query.skip = lastSkip;  //  ----> this results in some previous and some new items
}

let itemRows = await db.view('filters','blog', query);
let items = itemRows.rows;
// each doc is in items[].doc

我已经看到 ,排序对我有用 - 但我似乎无法使用分页。

我不确定 "I get the same lines again" 的说法。如果 startkey 是先前结果的第一个而不是最后一个键,那么这是可重现的——这将是 第一个 问题。

无论如何,假设 startkey 是正确的参数 skipstartkey 是冲突的。最初 skip 应为 0,之后应为 1,以便在后续查询中跳过 startkey

CouchDB 分页文档1 中清楚地概述了此技术。

详情

假设 complete 视图(其中键是 unix 时间戳)是

{
  "total_rows":7,
  "offset":0,
  "rows":[
    {"id":"821985c5140ca583e108653fb6091ac8","key":1580050872331,"value":null},
    {"id":"821985c5140ca583e108653fb6092c3b","key":1580050872332,"value":null},
    {"id":"821985c5140ca583e108653fb6093f47","key":1580050872333,"value":null},
    {"id":"821985c5140ca583e108653fb6094309","key":1580050872334,"value":null},
    {"id":"821985c5140ca583e108653fb6094463","key":1580050872335,"value":null},
    {"id":"821985c5140ca583e108653fb60945f4","key":1580050872336,"value":null},
    {"id":"821985c5140ca583e108653fb60949f3","key":1580050872339,"value":null}
  ]
}

给定初始查询条件

{
    limit: 5,
    descending: true,
    include_docs: false // for brevity
}

确实产生了预期的结果,5 行最近的排在第一位

{
  "total_rows":7,
  "offset":0,
  "rows":[
    {"id":"821985c5140ca583e108653fb60949f3","key":1580050872339,"value":null},
    {"id":"821985c5140ca583e108653fb60945f4","key":1580050872336,"value":null},
    {"id":"821985c5140ca583e108653fb6094463","key":1580050872335,"value":null},
    {"id":"821985c5140ca583e108653fb6094309","key":1580050872334,"value":null},
    {"id":"821985c5140ca583e108653fb6093f47","key":1580050872333,"value":null}
  ]
}

现在假设第二个查询是这样

{
    limit: 5,
    descending: true,
    include_docs: false, // for brevity
    startkey: 1580050872333,
    skip: 5
}

startkey(先前结果的最后一行的键)是正确的,但 skip 参数实际上是跳过了下一组(逻辑)行。特别是对于这些参数和上面的示例视图,查询将忽略剩余的键,从而导致空行集。

这是我们想要的:

{
    limit: 5,
    descending: true,
    include_docs: false, // for brevity
    startkey: 1580050872333,
    skip: 1 // just skip the last doc (startkey)
}


1 CouchDB 分页食谱 3.2.5.5. Paging (Alternate Method)

使用 startkey 或 skip,返回的结果也包括一些跳过的结果,或者所有以前的结果(奇怪地混淆)。

我通过使用 - 第二部分扩展结果键解决了这个问题。 由于密钥基于没有时间的日期,因此由于相似的日期时间戳,它似乎重新排列了每个请求的条目。添加第二部分也是可排序的(使用创建的时间戳作为第二部分)修复它。 现在的关键是 [datetimestamp, createdtimestamp] .. 两者都可以降序排列。