Подражать 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
    },
    ...
}
Другие вопросы по тегам