Подражать COUNT... GROUP BY в Cloudant (CouchDB)
В CloudAnt я хочу получить количество функций, сгруппированных по двум атрибутам: темам и советам. После долгих раздумий я смог построить это:
// map
function (doc) {
if (doc.properties && doc.properties.openCouncilDataTopic) {
var ret = {};
ret [doc.properties.openCouncilDataTopic] = {};
ret [doc.properties.openCouncilDataTopic][doc.properties.sourceCouncilId] = 1;
emit(null, ret);
}
}
// reduce
function (keys, values, rereduce) {
var ret = values[0];
function zero(x) { return x ? x : 0 }
function add(i, topic, id) {
ret[topic][id] = zero(ret[topic][id]) + values[i][topic][id];
}
function countTopic(topic) {
if (!ret[topic])
ret[topic] = {};
Object.keys(values[i][topic]).forEach(add.bind(undefined, i, topic));
}
for (var i = 1; i < values.length; i++) {
Object.keys(values[i]).forEach(countTopic);
}
return ret;
}
Есть ли способ лучше?
1 ответ
Да, есть лучший способ! Cloudant поддерживает " агрегирование по сложным ключам"
Вместо того, чтобы вручную рассчитывать количество, map
Функция может просто испускать ключи, которые являются атрибутами для группировки:
function (doc) {
if (doc.properties && doc.properties.openCouncilDataTopic) {
emit([doc.properties.openCouncilDataTopic, doc.properties.sourceCouncilId], 1);
}
}
Тогда мы можем использовать встроенный _count
уменьшить функцию.
Чтобы вызвать представление, добавьте group_by=2
где 2 - количество атрибутов для группировки. (По умолчанию 0 объединяет все до одного числа).
Вероятно, это будет намного быстрее, чем реализация счетчика в Javascript.
Одним из недостатков является то, что у нас меньше контроля над выводом, который выглядит так:
{
"rows": [
{
"key": [
"childcare-centres",
"https://data.gov.au/organization/cardinia-shire-council"
],
"value": 22
},
...
}