Reputation: 775
I've got a lot of records like:
{
"id": "1000",
"lastSeen": "2018-02-26T18:49:21.863Z"
}
{
"id": "1000",
"lastSeen": "2017-02-26T18:49:21.863Z"
}
{
"id": "2000",
"lastSeen": "2018-02-26T18:49:21.863Z"
}
{
"id": "2000",
"lastSeen": "2017-02-26T18:49:21.863Z"
}
I'd like to get the most recent records for all ids. So in this case the output would be the following(most recent record for ids 1000 and 2000):
{
"id": "1000",
"lastSeen": "2018-02-26T18:49:21.863Z"
}
{
"id": "2000",
"lastSeen": "2018-02-26T18:49:21.863Z"
}
With N1QL, this would be
SELECT id, MAX(lastSeen) FROM mybucket GROUP BY id
How would I do this using a couchbase view and map/reduce?
Thanks!
Upvotes: 1
Views: 33
Reputation: 663
You can query by descending and reduce to first one on list as below: Map:
function (doc, meta) {
emit(doc.id, doc.lastSeen);
}
Reduce:
function reduce(key, values, rereduce) {
return values[0];
}
Filter:
?inclusive_end=true&skip=0&full_set=&group_level=1&descending=true
This will eliminate the overhead of sorting the grouped values inside reduce function.
Upvotes: 0
Reputation: 26151
I am far from a regular user of map/reduce, and there may be more efficient JavaScript, but try this:
Map
function (doc, meta) {
emit(doc.id, doc.lastSeen);
}
Reduce
function reduce(key, values, rereduce) {
var max = values.sort().reverse()[0];
return max;
}
Filter: ?limit=6&stale=false&connection_timeout=60000&inclusive_end=true&skip=0&full_set=true&group_level=1
The idea is to sort all the values being emitted (lastSeen). Since they are ISO 8601 and can be lexigraphically sorted, sort()
works just fine. You want the latest, so that's what the reverse()
is for (otherwise you'd get the oldest).
The filter has a group_level of 1, so it will group by the doc.id
field.
Upvotes: 1