Experimental aggregation dimensions
This is not meant por public consumption (exposing SQL expressions is undesiderable)
This commit is contained in:
parent
0c044636ef
commit
6b472c0b20
@ -7,6 +7,7 @@
|
||||
* - sourceQuery
|
||||
* - res
|
||||
* - columns
|
||||
* - dimensions
|
||||
*/
|
||||
const templateForOptions = (options) => {
|
||||
let templateFn = aggregationQueryTemplates[options.placement];
|
||||
@ -23,11 +24,13 @@ const templateForOptions = (options) => {
|
||||
* aggregation cell is resolution*resolution pixels, where tiles are always 256x256 pixels
|
||||
* - columns
|
||||
* - placement
|
||||
* - dimensions
|
||||
*/
|
||||
const queryForOptions = (options) => templateForOptions(options)({
|
||||
sourceQuery: options.query,
|
||||
res: 256/options.resolution,
|
||||
columns: options.columns
|
||||
columns: options.columns,
|
||||
dimensions: options.dimensions
|
||||
});
|
||||
|
||||
module.exports = queryForOptions;
|
||||
@ -53,6 +56,11 @@ const SUPPORTED_AGGREGATE_FUNCTIONS = {
|
||||
}
|
||||
};
|
||||
|
||||
const sep = (list) => {
|
||||
let expr = list.join(', ');
|
||||
return expr ? ', ' + expr : expr;
|
||||
};
|
||||
|
||||
const aggregateColumns = ctx => {
|
||||
return Object.assign({
|
||||
_cdb_feature_count: {
|
||||
@ -63,12 +71,12 @@ const aggregateColumns = ctx => {
|
||||
|
||||
const aggregateColumnNames = ctx => {
|
||||
let columns = aggregateColumns(ctx);
|
||||
return Object.keys(columns).join(', ');
|
||||
return sep(Object.keys(columns));
|
||||
};
|
||||
|
||||
const aggregateColumnDefs = ctx => {
|
||||
let columns = aggregateColumns(ctx);
|
||||
return Object.keys(columns).map(column_name => {
|
||||
return sep(Object.keys(columns).map(column_name => {
|
||||
const aggregate_function = columns[column_name].aggregate_function || 'count';
|
||||
const aggregate_definition = SUPPORTED_AGGREGATE_FUNCTIONS[aggregate_function];
|
||||
if (!aggregate_definition) {
|
||||
@ -76,10 +84,24 @@ const aggregateColumnDefs = ctx => {
|
||||
}
|
||||
const aggregate_expression = aggregate_definition.sql(column_name, columns[column_name]);
|
||||
return `${aggregate_expression} AS ${column_name}`;
|
||||
}).join(', ');
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
const aggregateDimensions = ctx => ctx.dimensions || {};
|
||||
|
||||
const dimensionNames = ctx => {
|
||||
return sep(Object.keys(aggregateDimensions(ctx)));
|
||||
};
|
||||
|
||||
const dimensionDefs = ctx => {
|
||||
let dimensions = aggregateDimensions(ctx);
|
||||
return sep(Object.keys(dimensions).map(dimension_name => {
|
||||
const expression = dimensions[dimension_name];
|
||||
return `${expression} AS ${dimension_name}`;
|
||||
}));
|
||||
};
|
||||
|
||||
// SQL expression to compute the aggregation resolution (grid cell size).
|
||||
// This is equivalent to `${256/ctx.res}*CDB_XYZ_Resolution(CDB_ZoomFromScale(!scale_denominator!))`
|
||||
// This is defined by the ctx.res parameter, which is the number of grid cells per tile linear dimension
|
||||
@ -106,13 +128,15 @@ const aggregationQueryTemplates = {
|
||||
AVG(ST_X(_cdb_query.the_geom_webmercator)),
|
||||
AVG(ST_Y(_cdb_query.the_geom_webmercator))
|
||||
), 3857
|
||||
) AS the_geom_webmercator,
|
||||
) AS the_geom_webmercator
|
||||
${dimensionDefs(ctx)}
|
||||
${aggregateColumnDefs(ctx)}
|
||||
FROM (${ctx.sourceQuery}) _cdb_query, _cdb_params
|
||||
WHERE _cdb_query.the_geom_webmercator && _cdb_params.bbox
|
||||
GROUP BY
|
||||
Floor(ST_X(_cdb_query.the_geom_webmercator)/_cdb_params.res),
|
||||
Floor(ST_Y(_cdb_query.the_geom_webmercator)/_cdb_params.res)
|
||||
${dimensionNames(ctx)}
|
||||
`,
|
||||
|
||||
'point-grid': ctx => `
|
||||
@ -124,14 +148,16 @@ const aggregationQueryTemplates = {
|
||||
_cdb_clusters AS (
|
||||
SELECT
|
||||
Floor(ST_X(_cdb_query.the_geom_webmercator)/_cdb_params.res)::int AS _cdb_gx,
|
||||
Floor(ST_Y(_cdb_query.the_geom_webmercator)/_cdb_params.res)::int AS _cdb_gy,
|
||||
Floor(ST_Y(_cdb_query.the_geom_webmercator)/_cdb_params.res)::int AS _cdb_gy
|
||||
${dimensionDefs(ctx)}
|
||||
${aggregateColumnDefs(ctx)}
|
||||
FROM (${ctx.sourceQuery}) _cdb_query, _cdb_params
|
||||
FROM (${ctx.sourceQuery(ctx)}) _cdb_query, _cdb_params
|
||||
WHERE the_geom_webmercator && _cdb_params.bbox
|
||||
GROUP BY _cdb_gx, _cdb_gy
|
||||
GROUP BY _cdb_gx, _cdb_gy ${dimensionNames}
|
||||
)
|
||||
SELECT
|
||||
ST_SetSRID(ST_MakePoint(_cdb_gx*(res+0.5), _cdb_gy*(res+0.5)), 3857) AS the_geom_webmercator,
|
||||
ST_SetSRID(ST_MakePoint(_cdb_gx*(res+0.5), _cdb_gy*(res+0.5)), 3857) AS the_geom_webmercator
|
||||
${dimensionNames(ctx)}
|
||||
${aggregateColumnNames(ctx)}
|
||||
FROM _cdb_clusters, _cdb_params
|
||||
`,
|
||||
@ -143,19 +169,22 @@ const aggregationQueryTemplates = {
|
||||
!bbox! AS bbox
|
||||
), _cdb_clusters AS (
|
||||
SELECT
|
||||
MIN(cartodb_id) AS cartodb_id,
|
||||
MIN(cartodb_id) AS cartodb_id
|
||||
${dimensionDefs(ctx)}
|
||||
${aggregateColumnDefs(ctx)}
|
||||
FROM (${ctx.sourceQuery}) _cdb_query, _cdb_params
|
||||
FROM (${ctx.sourceQuery(ctx)}) _cdb_query, _cdb_params
|
||||
WHERE _cdb_query.the_geom_webmercator && _cdb_params.bbox
|
||||
GROUP BY
|
||||
Floor(ST_X(_cdb_query.the_geom_webmercator)/_cdb_params.res),
|
||||
Floor(ST_Y(_cdb_query.the_geom_webmercator)/_cdb_params.res)
|
||||
${dimensionNames(ctx)}
|
||||
) SELECT
|
||||
_cdb_clusters.cartodb_id,
|
||||
the_geom, the_geom_webmercator,
|
||||
the_geom, the_geom_webmercator
|
||||
${dimensionNames(ctx)}
|
||||
${aggregateColumnNames(ctx)}
|
||||
FROM
|
||||
_cdb_clusters INNER JOIN (${ctx.sourceQuery}) _cdb_query
|
||||
_cdb_clusters INNER JOIN (${ctx.sourceQuery(ctx)}) _cdb_query
|
||||
ON (_cdb_clusters.cartodb_id = _cdb_query.cartodb_id)
|
||||
`
|
||||
};
|
||||
|
@ -9,7 +9,8 @@ module.exports = class Aggregation {
|
||||
resolution = 1,
|
||||
threshold = Aggregation.THRESHOLD,
|
||||
placement = 'centroid',
|
||||
columns = {}
|
||||
columns = {},
|
||||
dimensions = {}
|
||||
} = {}) {
|
||||
this.mapconfig = mapconfig;
|
||||
this.query = query;
|
||||
@ -17,6 +18,7 @@ module.exports = class Aggregation {
|
||||
this.threshold = threshold;
|
||||
this.placement = placement;
|
||||
this.columns = columns;
|
||||
this.dimensions = dimensions;
|
||||
}
|
||||
sql () {
|
||||
return aggregationQuery(this);
|
||||
|
Loading…
Reference in New Issue
Block a user