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

时间:2020-01-25 08:14:29

标签: couchdb couchdb-nano

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

如果我运行它,则会获得前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

我看过sort by value,排序对我来说很有效-但我似乎无法进行分页工作。

2 个答案:

答案 0 :(得分:0)

对于“我再次得到同一行”这一说法,我不确定。如果startkey是先前结果的第一个键而不是最后一个键,则可以重现-这就是 first 问题。

无论如何,假设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)

答案 1 :(得分:0)

使用开始键或跳过键,返回的结果也包括一些跳过的结果,或者所有先前的结果(奇怪地混合在一起)。

我解决了它,方法是将结果键扩展为-第二部分。 由于密钥是基于没有时间的日期,因此由于类似的日期时间戳,它似乎已经重新排列了每个请求的条目。添加也可以排序的第二部分(将创建的时间戳用作第二部分)进行了修复。 密钥现在是[datetimestamp,createdtimestamp] ..都可以降序排列。