开发者

CouchDB pagination sorted by date, queried by id

I want to create pagination on application level using the CouchDB view API. The pagination uses cursors, so given a cursor, I will query the view for the n+1 documents starting with the given cursor as start key and output the n results as page and provide the n+1 result row as the cursor for the next page.

This works well as long as the view keys are also the keys for my view rows. Now this time all my docs have a date field and I emit them as map keys, because I want to sort via date. However, I can't use my cursors anymore like before.

I thought that is the reason the view API also provides startkey_docid for submitting such a cursor doc id, however this is obviously not true. It seems like this value is only applied if there are several equal rows per keys.

So, in short: I want a date-ordered view, but cursors based on the document ids. How can I do this?

Thanks in advance

Simplified view

function map(doc)
{
    emit(doc.date, {_id: doc._id});
}


Simplified view result:

{
"rows":[
    {"id":"123","key":"2010-06-26T01:28:13.555Z", value:{...}},
    {"id":"234","key":"2010-06-22T12:21:23.123Z", value:{...}},
    {"id":"987","key":"2010-06-16T13:48:43.321Z", value:{...}},
    {"id":"103","key":"2010-05-01T17:38:31.123Z", value:{...}},
    {"id":"645","key":"2009-07-21T21:21:13.345Z", value:{...}}
]
}

Application-level query with cursor 234, page size 3 should return:
    234, 987, 103

So how can I map t开发者_运维百科his to a view?


Why do you want cursors based on docid?

Map Reduce creates single dimensional indexes, so any non-key traversal will be expensive. However, I think you can do what you want without requiring traversing 2 indexes at the same time.

See for instance here how I paginate through a posts with a certain tag:

Sofa's CouchApp tag pagination

aka

http://jchris.couchone.com/sofa/_design/sofa/_list/index/tags?descending=true&reduce=false&limit=10&startkey=[%22life%22%2C{}]&endkey=[%22life%22]

The key in that view looks like ["tag","2008/10/25 04:49:10 +0000"] so you can paginate through by tag and, within tags, by time.

Edited

Ha! I just realized what you are trying to do. It is so very simple.

Forget all about docids, they should be random anyway and not related to anything so just forget docs even have ids for a second.

You say "Application-level query with cursor 234, page size 3 should return: 234, 987, 103"

Your cursor should not be 234. It should be the key "2010-06-22T12:21:23.123Z".

So in essence you use the key of the last row of results as the startkey for the next query. So eg startkey=""2010-06-22T12:21:23.123Z""&limit=3, then for each page you render, link to a query where the new startkey is the last returned key.

Bonus: with what I've just described, you will have the bottom row of page 2 be the top row of page 3. To fix this, add skip=1 to your query.

Bonus bonus: OK, what about when I have more than 3 docs that emitted to the same key in the view? Then the last key will always be the same as the first key, so you can't progress in pagination without expanding the limit parameter. Unless... you use startkey_docid (and set it do the id of the last row). That is the only time you should use startkey_docid.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜