diff --git a/lib/cartodb/utils/style/postgres-datasource.js b/lib/cartodb/utils/style/postgres-datasource.js index 5db35607..3e87f101 100644 --- a/lib/cartodb/utils/style/postgres-datasource.js +++ b/lib/cartodb/utils/style/postgres-datasource.js @@ -23,8 +23,35 @@ var methodTemplates = Object.keys(methods).reduce(function(methodTemplates, meth return methodTemplates; }, {}); +methodTemplates.category = dot.template([ + 'WITH', + 'categories AS (', + ' SELECT {{=it._column}} AS category, count(1) AS value, row_number() OVER (ORDER BY count(1) desc) as rank', + ' FROM ({{=it._sql}}) _cdb_aggregation_all', + ' GROUP BY {{=it._column}}', + ' ORDER BY 2 DESC', + '),', + 'agg_categories AS (', + ' SELECT \'__other\' category', + ' FROM categories', + ' WHERE rank >= {{=it._buckets}}', + ' GROUP BY 1', + ' UNION ALL', + ' SELECT CAST(category AS text)', + ' FROM categories', + ' WHERE rank < {{=it._buckets}}', + ')', + 'SELECT array_agg(category) AS category FROM agg_categories' +].join('\n')); + +var STRATEGY = { + SPLIT: 'split', + EXACT: 'exact' +}; + var method2strategy = { - headtails: 'split' + headtails: STRATEGY.SPLIT, + category: STRATEGY.EXACT }; function PostgresDatasource (pgQueryRunner, username, query) { @@ -38,7 +65,7 @@ PostgresDatasource.prototype.getName = function () { }; PostgresDatasource.prototype.getRamp = function (column, buckets, method, callback) { - var methodName = methods.hasOwnProperty(method) ? method : 'quantiles'; + var methodName = methodTemplates.hasOwnProperty(method) ? method : 'quantiles'; var template = methodTemplates[methodName]; var query = template({ _column: column, _sql: this.query, _buckets: buckets }); @@ -48,11 +75,15 @@ PostgresDatasource.prototype.getRamp = function (column, buckets, method, callba return callback(err); } - var ramp = result[0][methodName].sort(function(a, b) { - return a - b; - }); + var strategy = method2strategy[methodName]; + var ramp = result[0][methodName]; + if (strategy !== STRATEGY.EXACT) { + ramp = ramp.sort(function(a, b) { + return a - b; + }); + } - return callback(null, { ramp: ramp, strategy: method2strategy[methodName] }); + return callback(null, { ramp: ramp, strategy: strategy }); }); };