2016-02-13 01:38:06 +08:00
|
|
|
var queue = require('queue-async');
|
2016-03-17 19:50:42 +08:00
|
|
|
var debug = require('debug')('windshaft:analysis');
|
2016-02-13 01:38:06 +08:00
|
|
|
|
|
|
|
var camshaft = require('camshaft');
|
|
|
|
var dot = require('dot');
|
|
|
|
dot.templateSettings.strip = false;
|
|
|
|
|
2016-04-14 23:09:07 +08:00
|
|
|
function AnalysisMapConfigAdapter(analysisBackend) {
|
|
|
|
this.analysisBackend = analysisBackend;
|
2016-02-13 01:38:06 +08:00
|
|
|
}
|
|
|
|
|
2016-03-14 18:50:52 +08:00
|
|
|
module.exports = AnalysisMapConfigAdapter;
|
2016-02-13 01:38:06 +08:00
|
|
|
|
2016-03-02 19:42:42 +08:00
|
|
|
var SKIP_COLUMNS = {
|
|
|
|
'the_geom': true,
|
|
|
|
'the_geom_webmercator': true
|
|
|
|
};
|
|
|
|
|
|
|
|
function skipColumns(columnNames) {
|
|
|
|
return columnNames
|
|
|
|
.filter(function(columnName) { return !SKIP_COLUMNS[columnName]; });
|
|
|
|
}
|
2016-02-13 01:38:06 +08:00
|
|
|
|
|
|
|
var layerQueryTemplate = dot.template([
|
2016-04-14 23:09:07 +08:00
|
|
|
'SELECT {{=it._columns}}',
|
2016-02-13 01:38:06 +08:00
|
|
|
'FROM ({{=it._query}}) _cdb_analysis_query'
|
|
|
|
].join('\n'));
|
|
|
|
|
2016-03-02 19:42:42 +08:00
|
|
|
function layerQuery(query, columnNames) {
|
2016-04-14 23:09:07 +08:00
|
|
|
var _columns = ['ST_Transform(the_geom, 3857) the_geom_webmercator'].concat(skipColumns(columnNames));
|
|
|
|
return layerQueryTemplate({ _query: query, _columns: _columns.join(', ') });
|
2016-03-02 19:42:42 +08:00
|
|
|
}
|
|
|
|
|
2016-03-19 00:22:02 +08:00
|
|
|
function appendFiltersToNodes(requestMapConfig, dataviewsFiltersBySourceId) {
|
|
|
|
var analyses = requestMapConfig.analyses || [];
|
|
|
|
|
|
|
|
requestMapConfig.analyses = analyses.map(function(analysisDefinition) {
|
|
|
|
var analysisGraph = new camshaft.reference.AnalysisGraph(analysisDefinition);
|
|
|
|
var definition = analysisDefinition;
|
|
|
|
Object.keys(dataviewsFiltersBySourceId).forEach(function(sourceId) {
|
|
|
|
definition = analysisGraph.getDefinitionWith(sourceId, {filters: dataviewsFiltersBySourceId[sourceId] });
|
|
|
|
});
|
|
|
|
|
|
|
|
return definition;
|
|
|
|
});
|
|
|
|
|
|
|
|
return requestMapConfig;
|
|
|
|
}
|
|
|
|
|
2016-03-10 00:39:20 +08:00
|
|
|
function shouldAdaptLayers(requestMapConfig) {
|
|
|
|
return Array.isArray(requestMapConfig.layers) &&
|
|
|
|
Array.isArray(requestMapConfig.analyses) && requestMapConfig.analyses.length > 0;
|
2016-03-02 19:42:42 +08:00
|
|
|
}
|
|
|
|
|
2016-03-22 19:22:04 +08:00
|
|
|
var DATAVIEW_TYPE_2_FILTER_TYPE = {
|
|
|
|
aggregation: 'category',
|
|
|
|
histogram: 'range'
|
|
|
|
};
|
|
|
|
function getFilter(dataview, params) {
|
|
|
|
var type = dataview.type;
|
|
|
|
|
|
|
|
return {
|
|
|
|
type: DATAVIEW_TYPE_2_FILTER_TYPE[type],
|
|
|
|
column: dataview.options.column,
|
|
|
|
params: params
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-03-19 00:22:02 +08:00
|
|
|
AnalysisMapConfigAdapter.prototype.getLayers = function(analysisConfiguration, requestMapConfig, filters, callback) {
|
2016-03-19 00:31:28 +08:00
|
|
|
// jshint maxcomplexity:7
|
2016-04-14 23:09:07 +08:00
|
|
|
var self = this;
|
2016-03-19 00:22:02 +08:00
|
|
|
filters = filters || {};
|
2016-04-20 21:40:14 +08:00
|
|
|
|
|
|
|
if (!shouldAdaptLayers(requestMapConfig)) {
|
|
|
|
return callback(null, requestMapConfig);
|
|
|
|
}
|
|
|
|
|
2016-03-19 00:22:02 +08:00
|
|
|
var dataviewsFilters = filters.dataviews || {};
|
|
|
|
debug(dataviewsFilters);
|
|
|
|
var dataviews = requestMapConfig.dataviews || {};
|
|
|
|
|
|
|
|
var dataviewsFiltersBySourceId = Object.keys(dataviewsFilters).reduce(function(bySourceId, dataviewName) {
|
|
|
|
var dataview = dataviews[dataviewName];
|
|
|
|
if (dataview) {
|
|
|
|
var sourceId = dataview.source.id;
|
|
|
|
if (!bySourceId.hasOwnProperty(sourceId)) {
|
|
|
|
bySourceId[sourceId] = {};
|
|
|
|
}
|
|
|
|
|
2016-03-22 19:22:04 +08:00
|
|
|
bySourceId[sourceId][dataviewName] = getFilter(dataview, dataviewsFilters[dataviewName]);
|
2016-03-19 00:22:02 +08:00
|
|
|
}
|
|
|
|
return bySourceId;
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
debug(dataviewsFiltersBySourceId);
|
2016-02-20 00:13:28 +08:00
|
|
|
|
2016-03-17 19:50:42 +08:00
|
|
|
debug('mapconfig input', JSON.stringify(requestMapConfig, null, 4));
|
|
|
|
|
2016-03-22 01:02:19 +08:00
|
|
|
requestMapConfig = appendFiltersToNodes(requestMapConfig, dataviewsFiltersBySourceId);
|
2016-03-19 00:28:36 +08:00
|
|
|
|
2016-03-10 00:39:20 +08:00
|
|
|
function createAnalysis(analysisDefinition, done) {
|
2016-04-14 23:09:07 +08:00
|
|
|
self.analysisBackend.create(analysisConfiguration, analysisDefinition, done);
|
2016-02-13 01:38:06 +08:00
|
|
|
}
|
|
|
|
|
2016-03-10 00:39:20 +08:00
|
|
|
var analysesQueue = queue(requestMapConfig.analyses.length);
|
|
|
|
requestMapConfig.analyses.forEach(function(analysis) {
|
|
|
|
analysesQueue.defer(createAnalysis, analysis);
|
|
|
|
});
|
|
|
|
|
|
|
|
analysesQueue.awaitAll(function(err, analysesResults) {
|
2016-02-13 01:38:06 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
|
2016-03-10 00:39:20 +08:00
|
|
|
var sourceId2Node = analysesResults.reduce(function(sourceId2Query, analysis) {
|
|
|
|
var rootNode = analysis.getRoot();
|
|
|
|
if (rootNode.params && rootNode.params.id) {
|
|
|
|
sourceId2Query[rootNode.params.id] = rootNode;
|
|
|
|
}
|
2016-02-13 01:38:06 +08:00
|
|
|
|
2016-03-10 00:39:20 +08:00
|
|
|
analysis.getSortedNodes().forEach(function(node) {
|
|
|
|
if (node.params && node.params.id) {
|
|
|
|
sourceId2Query[node.params.id] = node;
|
|
|
|
}
|
|
|
|
});
|
2016-02-13 01:38:06 +08:00
|
|
|
|
2016-03-10 00:39:20 +08:00
|
|
|
return sourceId2Query;
|
|
|
|
}, {});
|
2016-02-13 01:38:06 +08:00
|
|
|
|
2016-03-10 00:39:20 +08:00
|
|
|
requestMapConfig.layers = requestMapConfig.layers.map(function(layer) {
|
|
|
|
if (layer.options.source && layer.options.source.id) {
|
|
|
|
var layerNode = sourceId2Node[layer.options.source.id];
|
|
|
|
layer.options.sql = layerQuery(layerNode.getQuery(), layerNode.getColumns());
|
|
|
|
}
|
|
|
|
return layer;
|
2016-02-13 01:38:06 +08:00
|
|
|
});
|
2016-03-10 00:39:20 +08:00
|
|
|
|
2016-03-17 19:50:42 +08:00
|
|
|
debug('mapconfig output', JSON.stringify(requestMapConfig, null, 4));
|
|
|
|
|
2016-04-07 23:58:12 +08:00
|
|
|
return callback(null, requestMapConfig, analysesResults);
|
2016-03-10 00:39:20 +08:00
|
|
|
});
|
2016-02-13 01:38:06 +08:00
|
|
|
};
|