I have a requirement to get the most recent documents given a bunch of keys. Imagine a chat-room document, and chat-message documents that have a chatRoomId, a timestamp and some content:
I want to get the latest chatMessage for each chat-room, or for set of chat-rooms. My current solution is to have a view, indexed by chatRoomId and timestamp:
The solution isnât good though. To get the most recent message for multiple chat rooms I need to issue many queries and collect up the results. Is there something better I could try? Perhaps a reduced view?
I implemented exactly this for an unfinished chat sample app a few years ago. (It might still be around in the couchbaselabs org on Github â it was called âCouchChatâ or something like that.)
The answer is to use grouping. Set the group level to 1, which will aggregate all the rows of each chatRoomID, and use a reduce function that simply returns the second component of the first key (which, if you issue a descending query, will be the largest date.)
Thanks jens - is this the project? Not quite sure what you mean by âgroupingâ, can you point em at some docs (this is all I could find)? I think I understandâŚ
Ah, I think Iâve got it. So the reduce function looks like this:
"reduce": function (keys, values) {
return keys[0][1];
}
And the query only has these parameters:
{
descending: true,
group_level: 1,
}
Which gives me a single result (the most recent) for each group. But it doesnât return the document id, and adding include_docs=true doesnât seem to return the documents. So do I have the then re-query to pull the documents out?
Yes, reduced queries return aggregate data so the rows are no longer associated with documents.
I think youâd need to add the docID to the value emitted by the map function; then you can return it from the reduce function together with the date.
Oh, and you asked when the reduce happens. In Couchbase server, as in CouchDB, reduced values are stored in the index B-tree to make querying faster. I couldnât figure out a way to reproduce this without having access to the innards of the storage engine, so Couchbase Lite does the reducing as part of each query. So far it seems to be fast enough, for the smaller data sets used on mobile.
So do reduced views behave differently in CBL to couchbase? In CBL the parameters are applied when the view is queried, and the results are reduced. But in couchbase, if the views are already reduced I assume the parameters are applied to the to reduced view⌠or are the just ignored?
Still canât get _bulk_get working in order to get my docs back the now that Iâve collected up the docs ids. Its 404ing. Iâm currently using the _all_docs endpoint with keys=[...]&include_docs=true but its quite limited because the query string gets too long.
The output of the reduced query is identical either way. Couchbase Server / CouchDB are just pre-caching (âmemoizingâ) reduced values in the persistent index to speed up the computations.
I believe we forgot to implement _bulk_get in Couchbase Lite, embarrassingly. A workaround is to use an _all_docs query and provide a keys parameter with the doc IDs you want.