Merge pull request #809 from CartoDB/analyses-filters-params
Add `no_filters` param to dataviews
This commit is contained in:
commit
8e9f61f9f1
3
NEWS.md
3
NEWS.md
@ -4,7 +4,8 @@
|
|||||||
Released 2017-mm-dd
|
Released 2017-mm-dd
|
||||||
|
|
||||||
Announcements:
|
Announcements:
|
||||||
- Logging all errors
|
- Logging all errors.
|
||||||
|
- Histograms: Now they accept a `no_filters` parameter.
|
||||||
|
|
||||||
## 4.4.0
|
## 4.4.0
|
||||||
Released 2017-12-12
|
Released 2017-12-12
|
||||||
|
@ -37,12 +37,19 @@ DataviewBackend.prototype.getDataview = function (mapConfigProvider, user, param
|
|||||||
throw new Error("Dataview '" + dataviewName + "' does not exists");
|
throw new Error("Dataview '" + dataviewName + "' does not exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
var pg = new PSQL(dbParamsFromReqParams(params));
|
|
||||||
|
|
||||||
var ownFilter = +params.own_filter;
|
var ownFilter = +params.own_filter;
|
||||||
ownFilter = !!ownFilter;
|
var noFilters = +params.no_filters;
|
||||||
|
if (Number.isFinite(ownFilter) && Number.isFinite(noFilters)) {
|
||||||
|
err = new Error();
|
||||||
|
err.message = 'Both own_filter and no_filters cannot be sent in the same request';
|
||||||
|
err.type = 'dataview';
|
||||||
|
err.http_status = 400;
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
var query = (ownFilter) ? dataviewDefinition.sql.own_filter_on : dataviewDefinition.sql.own_filter_off;
|
var pg = new PSQL(dbParamsFromReqParams(params));
|
||||||
|
|
||||||
|
var query = getDataviewQuery(dataviewDefinition, ownFilter, noFilters);
|
||||||
if (params.bbox) {
|
if (params.bbox) {
|
||||||
var bboxFilter = new BBoxFilter({column: 'the_geom_webmercator', srid: 3857}, {bbox: params.bbox});
|
var bboxFilter = new BBoxFilter({column: 'the_geom_webmercator', srid: 3857}, {bbox: params.bbox});
|
||||||
query = bboxFilter.sql(query);
|
query = bboxFilter.sql(query);
|
||||||
@ -55,7 +62,7 @@ DataviewBackend.prototype.getDataview = function (mapConfigProvider, user, param
|
|||||||
);
|
);
|
||||||
|
|
||||||
var dataview = dataviewFactory.getDataview(query, dataviewDefinition);
|
var dataview = dataviewFactory.getDataview(query, dataviewDefinition);
|
||||||
dataview.getResult(pg, getOverrideParams(params, ownFilter), this);
|
dataview.getResult(pg, getOverrideParams(params, !!ownFilter), this);
|
||||||
},
|
},
|
||||||
function returnCallback(err, result) {
|
function returnCallback(err, result) {
|
||||||
return callback(err, result);
|
return callback(err, result);
|
||||||
@ -63,6 +70,16 @@ DataviewBackend.prototype.getDataview = function (mapConfigProvider, user, param
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getDataviewQuery(dataviewDefinition, ownFilter, noFilters) {
|
||||||
|
if (noFilters) {
|
||||||
|
return dataviewDefinition.sql.no_filters;
|
||||||
|
} else if (ownFilter === 1) {
|
||||||
|
return dataviewDefinition.sql.own_filter_on;
|
||||||
|
} else {
|
||||||
|
return dataviewDefinition.sql.own_filter_off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getQueryRewriteData(mapConfig, dataviewDefinition, params) {
|
function getQueryRewriteData(mapConfig, dataviewDefinition, params) {
|
||||||
var sourceId = dataviewDefinition.source.id; // node.id
|
var sourceId = dataviewDefinition.source.id; // node.id
|
||||||
var layer = _.find(mapConfig.obj().layers, function(l) {
|
var layer = _.find(mapConfig.obj().layers, function(l) {
|
||||||
|
@ -106,6 +106,7 @@ LayergroupController.prototype.register = function(app) {
|
|||||||
var allowedDataviewQueryParams = [
|
var allowedDataviewQueryParams = [
|
||||||
'filters', // json
|
'filters', // json
|
||||||
'own_filter', // 0, 1
|
'own_filter', // 0, 1
|
||||||
|
'no_filters', // 0, 1
|
||||||
'bbox', // w,s,e,n
|
'bbox', // w,s,e,n
|
||||||
'start', // number
|
'start', // number
|
||||||
'end', // number
|
'end', // number
|
||||||
|
@ -58,6 +58,13 @@ AnalysisMapConfigAdapter.prototype.getMapConfig = function(user, requestMapConfi
|
|||||||
|
|
||||||
requestMapConfig = appendFiltersToNodes(requestMapConfig, dataviewsFiltersBySourceId);
|
requestMapConfig = appendFiltersToNodes(requestMapConfig, dataviewsFiltersBySourceId);
|
||||||
|
|
||||||
|
// Expected format for analyses filters
|
||||||
|
// filters = {analyses: {
|
||||||
|
// a1: [{min, max}, {accept, reject}],
|
||||||
|
// b1: [{range, column, min, max}, {category, column, accept, reject}]
|
||||||
|
// }}
|
||||||
|
requestMapConfig = appendFiltersToNodes(requestMapConfig, filters.analyses);
|
||||||
|
|
||||||
function createAnalysis(analysisDefinition, done) {
|
function createAnalysis(analysisDefinition, done) {
|
||||||
self.analysisBackend.create(analysisConfiguration, analysisDefinition, function (err, analysis) {
|
self.analysisBackend.create(analysisConfiguration, analysisDefinition, function (err, analysis) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -200,6 +207,7 @@ function dataviewQuery(node, dataviewName, ownFilter) {
|
|||||||
|
|
||||||
function appendFiltersToNodes(requestMapConfig, dataviewsFiltersBySourceId) {
|
function appendFiltersToNodes(requestMapConfig, dataviewsFiltersBySourceId) {
|
||||||
var analyses = requestMapConfig.analyses || [];
|
var analyses = requestMapConfig.analyses || [];
|
||||||
|
dataviewsFiltersBySourceId = dataviewsFiltersBySourceId || {};
|
||||||
|
|
||||||
requestMapConfig.analyses = analyses.map(function(analysisDefinition) {
|
requestMapConfig.analyses = analyses.map(function(analysisDefinition) {
|
||||||
var analysisGraph = new camshaft.reference.AnalysisGraph(analysisDefinition);
|
var analysisGraph = new camshaft.reference.AnalysisGraph(analysisDefinition);
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
"Sandro Santilli <strk@vizzuality.com>",
|
"Sandro Santilli <strk@vizzuality.com>",
|
||||||
"Carlos Matallín <matallo@carto.com>",
|
"Carlos Matallín <matallo@carto.com>",
|
||||||
"Daniel Garcia Aubert <dgaubert@carto.com>",
|
"Daniel Garcia Aubert <dgaubert@carto.com>",
|
||||||
"Mario de Frutos <mario.defrutos@carto.com>"
|
"Mario de Frutos <mario.defrutos@carto.com>",
|
||||||
|
"Ivan Malagon <ivan@carto.com>",
|
||||||
|
"Simon Martin <simon@carto.com>"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
|
150
test/acceptance/analysis/analyses-filters-params.js
Normal file
150
test/acceptance/analysis/analyses-filters-params.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
require('../../support/test_helper');
|
||||||
|
|
||||||
|
const assert = require('../../support/assert');
|
||||||
|
const TestClient = require('../../support/test-client');
|
||||||
|
|
||||||
|
describe('analysis-filters-params', () => {
|
||||||
|
|
||||||
|
const CARTOCSS = `#layer {
|
||||||
|
marker-fill-opacity: 1;
|
||||||
|
marker-line-color: white;
|
||||||
|
marker-line-width: 0.5;
|
||||||
|
marker-line-opacity: 1;
|
||||||
|
marker-placement: point;
|
||||||
|
marker-type: ellipse;
|
||||||
|
marker-width: 8;
|
||||||
|
marker-fill: red;
|
||||||
|
marker-allow-overlap: true;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const mapConfig = {
|
||||||
|
version: '1.6.0',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
"type": "cartodb",
|
||||||
|
"options": {
|
||||||
|
"source": {
|
||||||
|
"id": "a1"
|
||||||
|
},
|
||||||
|
"cartocss": CARTOCSS,
|
||||||
|
"cartocss_version": "2.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataviews: {
|
||||||
|
pop_max_histogram: {
|
||||||
|
source: {
|
||||||
|
id: 'a1'
|
||||||
|
},
|
||||||
|
type: 'histogram',
|
||||||
|
options: {
|
||||||
|
column: 'pop_max'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pop_min_histogram: {
|
||||||
|
source: {
|
||||||
|
id: 'a1'
|
||||||
|
},
|
||||||
|
type: 'histogram',
|
||||||
|
options: {
|
||||||
|
column: 'pop_min'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
analyses: [
|
||||||
|
{
|
||||||
|
"id": "a1",
|
||||||
|
"type": "source",
|
||||||
|
"params": {
|
||||||
|
"query": "select * from populated_places_simple_reduced"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
var params = {
|
||||||
|
filters: {
|
||||||
|
dataviews: {
|
||||||
|
pop_max_histogram: {
|
||||||
|
min: 2e6
|
||||||
|
},
|
||||||
|
pop_min_histogram: {
|
||||||
|
max: 2e6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
it('should get a filtered histogram dataview with all filters', function(done) {
|
||||||
|
const testClient = new TestClient(mapConfig, 1234);
|
||||||
|
const testParams = Object.assign({}, params, {
|
||||||
|
own_filter: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
testClient.getDataview('pop_max_histogram', testParams, (err, dataview) => {
|
||||||
|
assert.ok(!err, err);
|
||||||
|
|
||||||
|
assert.equal(dataview.type, 'histogram');
|
||||||
|
assert.equal(dataview.bins_count, 6);
|
||||||
|
|
||||||
|
testClient.drain(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get a filtered histogram dataview with all filters except my own filter', function(done) {
|
||||||
|
const testClient = new TestClient(mapConfig, 1234);
|
||||||
|
const testParams = Object.assign({}, params, {
|
||||||
|
own_filter: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
testClient.getDataview('pop_max_histogram', testParams, (err, dataview) => {
|
||||||
|
assert.ok(!err, err);
|
||||||
|
|
||||||
|
assert.equal(dataview.type, 'histogram');
|
||||||
|
assert.equal(dataview.bins_count, 24);
|
||||||
|
|
||||||
|
testClient.drain(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get a filtered histogram dataview without filters', function(done) {
|
||||||
|
const testClient = new TestClient(mapConfig, 1234);
|
||||||
|
const testParams = Object.assign({}, params, {
|
||||||
|
no_filters: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
testClient.getDataview('pop_max_histogram', testParams, (err, dataview) => {
|
||||||
|
assert.ok(!err, err);
|
||||||
|
|
||||||
|
assert.equal(dataview.type, 'histogram');
|
||||||
|
assert.equal(dataview.bins_count, 48);
|
||||||
|
|
||||||
|
testClient.drain(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an error if both no_filters and own_filter params are present', function (done) {
|
||||||
|
const testClient = new TestClient(mapConfig, 1234);
|
||||||
|
const expectedError = {
|
||||||
|
errors: ['Both own_filter and no_filters cannot be sent in the same request'],
|
||||||
|
errors_with_context: [{
|
||||||
|
type: 'dataview',
|
||||||
|
message: 'Both own_filter and no_filters cannot be sent in the same request'
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
const testParams = Object.assign({}, params, {
|
||||||
|
no_filters: 1,
|
||||||
|
own_filter: 0,
|
||||||
|
response: {
|
||||||
|
status: 400
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
testClient.getDataview('pop_max_histogram', testParams, (err, dataview) => {
|
||||||
|
assert.deepEqual(dataview, expectedError);
|
||||||
|
|
||||||
|
testClient.drain(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
84
test/acceptance/analysis/analyses-filters.js
Normal file
84
test/acceptance/analysis/analyses-filters.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
require('../../support/test_helper');
|
||||||
|
|
||||||
|
const assert = require('../../support/assert');
|
||||||
|
const TestClient = require('../../support/test-client');
|
||||||
|
|
||||||
|
describe('analysis-layers-dataviews', () => {
|
||||||
|
|
||||||
|
const CARTOCSS = `#layer {
|
||||||
|
marker-fill-opacity: 1;
|
||||||
|
marker-line-color: white;
|
||||||
|
marker-line-width: 0.5;
|
||||||
|
marker-line-opacity: 1;
|
||||||
|
marker-placement: point;
|
||||||
|
marker-type: ellipse;
|
||||||
|
marker-width: 8;
|
||||||
|
marker-fill: red;
|
||||||
|
marker-allow-overlap: true;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const mapConfig = {
|
||||||
|
version: '1.6.0',
|
||||||
|
layers: [
|
||||||
|
{
|
||||||
|
"type": "cartodb",
|
||||||
|
"options": {
|
||||||
|
"source": {
|
||||||
|
"id": "a1"
|
||||||
|
},
|
||||||
|
"cartocss": CARTOCSS,
|
||||||
|
"cartocss_version": "2.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataviews: {
|
||||||
|
pop_max_histogram: {
|
||||||
|
source: {
|
||||||
|
id: 'a1'
|
||||||
|
},
|
||||||
|
type: 'histogram',
|
||||||
|
options: {
|
||||||
|
column: 'pop_max'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
analyses: [
|
||||||
|
{
|
||||||
|
"id": "a1",
|
||||||
|
"type": "source",
|
||||||
|
"params": {
|
||||||
|
"query": "select * from populated_places_simple_reduced"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should get a filtered histogram dataview', function(done) {
|
||||||
|
const testClient = new TestClient(mapConfig, 1234);
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
filters: {
|
||||||
|
analyses: {
|
||||||
|
'a1': [
|
||||||
|
{
|
||||||
|
type: 'range',
|
||||||
|
column: 'pop_max',
|
||||||
|
params: {
|
||||||
|
min: 2e6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
testClient.getDataview('pop_max_histogram', params, (err, dataview) => {
|
||||||
|
assert.ok(!err, err);
|
||||||
|
|
||||||
|
assert.equal(dataview.type, 'histogram');
|
||||||
|
assert.equal(dataview.bins_start, 2008000);
|
||||||
|
|
||||||
|
testClient.drain(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -109,7 +109,8 @@ describe('analysis-layers-dataviews', function() {
|
|||||||
min: 2e6
|
min: 2e6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
own_filter: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
testClient.getDataview('pop_max_histogram', params, function(err, dataview) {
|
testClient.getDataview('pop_max_histogram', params, function(err, dataview) {
|
||||||
|
@ -393,7 +393,8 @@ describe('dataviews using tables with overviews', function() {
|
|||||||
var params = {
|
var params = {
|
||||||
filters: {
|
filters: {
|
||||||
dataviews: { test_histogram: { min: 2 } }
|
dataviews: { test_histogram: { min: 2 } }
|
||||||
}
|
},
|
||||||
|
own_filter: 1
|
||||||
};
|
};
|
||||||
var testClient = new TestClient(overviewsMapConfig);
|
var testClient = new TestClient(overviewsMapConfig);
|
||||||
testClient.getDataview('test_histogram', params, function (err, histogram) {
|
testClient.getDataview('test_histogram', params, function (err, histogram) {
|
||||||
@ -412,7 +413,8 @@ describe('dataviews using tables with overviews', function() {
|
|||||||
var params = {
|
var params = {
|
||||||
filters: {
|
filters: {
|
||||||
dataviews: { test_histogram: { max: -1 } }
|
dataviews: { test_histogram: { max: -1 } }
|
||||||
}
|
},
|
||||||
|
own_filter: 1
|
||||||
};
|
};
|
||||||
var testClient = new TestClient(overviewsMapConfig);
|
var testClient = new TestClient(overviewsMapConfig);
|
||||||
testClient.getDataview('test_histogram', params, function (err, histogram) {
|
testClient.getDataview('test_histogram', params, function (err, histogram) {
|
||||||
@ -433,7 +435,8 @@ describe('dataviews using tables with overviews', function() {
|
|||||||
var params = {
|
var params = {
|
||||||
filters: {
|
filters: {
|
||||||
dataviews: { test_histogram_date: { max: -1 } }
|
dataviews: { test_histogram_date: { max: -1 } }
|
||||||
}
|
},
|
||||||
|
own_filter: 1
|
||||||
};
|
};
|
||||||
var testClient = new TestClient(overviewsMapConfig);
|
var testClient = new TestClient(overviewsMapConfig);
|
||||||
testClient.getDataview('test_histogram_date', params, function (err, histogram) {
|
testClient.getDataview('test_histogram_date', params, function (err, histogram) {
|
||||||
|
@ -411,9 +411,13 @@ TestClient.prototype.getDataview = function(dataviewName, params, callback) {
|
|||||||
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
||||||
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||||
|
|
||||||
var urlParams = {
|
var urlParams = {};
|
||||||
own_filter: params.hasOwnProperty('own_filter') ? params.own_filter : 1
|
if (params.hasOwnProperty('no_filters')) {
|
||||||
};
|
urlParams.no_filters = params.no_filters;
|
||||||
|
}
|
||||||
|
if (params.hasOwnProperty('own_filter')) {
|
||||||
|
urlParams.own_filter = params.own_filter;
|
||||||
|
}
|
||||||
|
|
||||||
['bbox', 'bins', 'start', 'end', 'aggregation', 'offset', 'categories'].forEach(function(extraParam) {
|
['bbox', 'bins', 'start', 'end', 'aggregation', 'offset', 'categories'].forEach(function(extraParam) {
|
||||||
if (params.hasOwnProperty(extraParam)) {
|
if (params.hasOwnProperty(extraParam)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user