Одним из решений было бы написать ваше представление для использования сложного ключа, такого как:
function (doc) {
emit([doc.user, doc.count], doc.item);
}
Если вы добавите descending=true
в строку запроса, это даст вам такой результат просмотра, как:
{"total_rows":4,"offset":0,"rows":[
{"id":"53f359b7cd360da296dd9aab3d0029bd","key":["john",15],"value":"D"},
{"id":"53f359b7cd360da296dd9aab3d001a0e","key":["bob",30],"value":"B"},
{"id":"53f359b7cd360da296dd9aab3d000fec","key":["bob",20],"value":"A"},
{"id":"53f359b7cd360da296dd9aab3d002668","key":["bob",10],"value":"C"}
]}
Это уже отсортировано по пользователю, затем посчитайте. (с типом элемента в качестве значения)
Тогда вы можете использовать _list
функцию , чтобы сделать все остальное. Приведенный ниже код в основном перебирает представление и возвращает 2 лучших результата для каждого пользователя. Если вы укажете user=bob
в строке запроса, вы получите результаты только для bob
.
function (head, req) {
// specify that we're sending JSON as our response
provides('json', function () {
var results = [],
result, user, count, row;
while (row = getRow()) {
// if the user doesn't match the last iteration, reset our counter
if (user != row.key[0]) {
user = row.key[0];
count = 0;
}
// we only need the top 2
if (count++ >= 2) {
continue;
}
// start building a result object
result = {
item: row.value,
count: row.key[1]
};
// if we provide user=?
if (req.query.user) {
// check to see if it matches the current user
if (req.query.user === user) {
// if so, add it to the results
results.push(result);
}
// by default, we'll return the top 2 for every user
} else {
// add the user key to the result object
result.user = row.key[0];
// and add it to the result set
results.push(result);
}
}
// send outside the loop, since it needs to be sent as valid JSON
send(JSON.stringify(results));
});
}