278 lines
6.2 KiB
Markdown
278 lines
6.2 KiB
Markdown
|
# 1. Purpose
|
|||
|
|
|||
|
This specification describes an extension for
|
|||
|
[MapConfig 1.4.0](https://github.com/CartoDB/Windshaft/blob/master/doc/MapConfig-1.4.0.md) version.
|
|||
|
|
|||
|
|
|||
|
# 2. Changes over specification
|
|||
|
|
|||
|
This extension depends on Analyses extension. It extends MapConfig with a new attribute: `dataviews`.
|
|||
|
|
|||
|
It makes possible to get tabular data from analysis nodes: aggregated lists, aggregations, and histograms.
|
|||
|
|
|||
|
## 2.1. Dataview types
|
|||
|
|
|||
|
### Aggregation
|
|||
|
|
|||
|
An aggregation is a list with aggregated results by a column and a given aggregation function.
|
|||
|
|
|||
|
Definition
|
|||
|
```
|
|||
|
{
|
|||
|
// REQUIRED
|
|||
|
// string, `type` the aggregation type
|
|||
|
“type”: “aggregation”,
|
|||
|
// REQUIRED
|
|||
|
// object, `options` dataview params
|
|||
|
“options”: {
|
|||
|
// REQUIRED
|
|||
|
// string, `column` column name to aggregate by
|
|||
|
“column”: “country”,
|
|||
|
// REQUIRED
|
|||
|
// string, `aggregation` operation to perform
|
|||
|
“aggregation”: “count”
|
|||
|
// OPTIONAL
|
|||
|
// string, `aggregationColumn` column value to aggregate
|
|||
|
// This param is required when `aggregation` is different than "count"
|
|||
|
“aggregationColumn”: “population”
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Expected output
|
|||
|
```
|
|||
|
{
|
|||
|
"type": "aggregation",
|
|||
|
"categories": [
|
|||
|
{
|
|||
|
"category": "foo",
|
|||
|
"value": 100
|
|||
|
},
|
|||
|
{
|
|||
|
"category": "bar",
|
|||
|
"value": 200
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### Histograms
|
|||
|
|
|||
|
Histograms represent the data distribution for a column.
|
|||
|
|
|||
|
Definition
|
|||
|
```
|
|||
|
{
|
|||
|
// REQUIRED
|
|||
|
// string, `type` the histogram type
|
|||
|
“type”: “histogram”,
|
|||
|
// REQUIRED
|
|||
|
// object, `options` dataview params
|
|||
|
“options”: {
|
|||
|
// REQUIRED
|
|||
|
// string, `column` column name to aggregate by
|
|||
|
“column”: “name”,
|
|||
|
// OPTIONAL
|
|||
|
// number, `bins` how many buckets the histogram should use
|
|||
|
“bins”: 10
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Expected output
|
|||
|
```
|
|||
|
{
|
|||
|
"type": "histogram",
|
|||
|
"bins": [{"bin": 0, "start": 2, "end": 2, "min": 2, "max": 2, "freq": 1}, null, null, {"bin": 3, "min": 40, "max": 44, "freq": 2}, null],
|
|||
|
"width": 10
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### Formula
|
|||
|
|
|||
|
Formulas given a final value representing the whole dataset.
|
|||
|
|
|||
|
Definition
|
|||
|
```
|
|||
|
{
|
|||
|
// REQUIRED
|
|||
|
// string, `type` the formula type
|
|||
|
“type”: “formula”,
|
|||
|
// REQUIRED
|
|||
|
// object, `options` dataview params
|
|||
|
“options”: {
|
|||
|
// REQUIRED
|
|||
|
// string, `column` column name to aggregate by
|
|||
|
“column”: “name”,
|
|||
|
// REQUIRED
|
|||
|
// string, `aggregation` operation to perform
|
|||
|
“operation”: “count”
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Operation must be: “min”, “max”, “count”, “avg”, or “sum”.
|
|||
|
|
|||
|
Result
|
|||
|
```
|
|||
|
{
|
|||
|
"type": "formula",
|
|||
|
"operation": "count",
|
|||
|
"result": 1000,
|
|||
|
"nulls": 0
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
## 2.2 Dataviews attribute
|
|||
|
|
|||
|
The new dataviews attribute must be a dictionary of dataviews.
|
|||
|
|
|||
|
An analysis node id can be referenced from dataviews to consume its output query.
|
|||
|
|
|||
|
|
|||
|
The layer consuming the output must reference it with the following option:
|
|||
|
|
|||
|
```
|
|||
|
{
|
|||
|
// REQUIRED
|
|||
|
// object, `source` as in the future we might want to have other source options
|
|||
|
"source": {
|
|||
|
// REQUIRED
|
|||
|
// string, `id` the analysis node identifier
|
|||
|
"id": "HEAD"
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 2.3. Complete example
|
|||
|
|
|||
|
```
|
|||
|
{
|
|||
|
"version": "1.4.0",
|
|||
|
"layers": [
|
|||
|
{
|
|||
|
"type": "cartodb",
|
|||
|
"options": {
|
|||
|
"source": {
|
|||
|
"id": "HEAD"
|
|||
|
},
|
|||
|
"cartocss": "...",
|
|||
|
"cartocss_version": "2.3.0"
|
|||
|
}
|
|||
|
}
|
|||
|
],
|
|||
|
"dataviews" {
|
|||
|
"basic_histogram": {
|
|||
|
"source": {
|
|||
|
"id": "HEAD"
|
|||
|
},
|
|||
|
"type": "histogram",
|
|||
|
"options": {
|
|||
|
"column": "pop_max"
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
"analyses": [
|
|||
|
{
|
|||
|
"id": "HEAD",
|
|||
|
"type": "source",
|
|||
|
"params": {
|
|||
|
"query": "select * from your_table"
|
|||
|
}
|
|||
|
}
|
|||
|
]
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 3. Filters
|
|||
|
|
|||
|
Camshaft's analyses expose a filtering capability and `aggregation` and `histogram` dataviews get them for free with
|
|||
|
this extension. Filters are available with the very dataview id, so if you have a "basic_histogram" histogram dataview
|
|||
|
you can filter with a range filter with "basic_histogram" name.
|
|||
|
|
|||
|
|
|||
|
## 3.1 Filter types
|
|||
|
|
|||
|
### Category
|
|||
|
|
|||
|
Allows to remove results that are not contained within a set of elements.
|
|||
|
Initially this filter can be applied to a `numeric` or `text` columns.
|
|||
|
|
|||
|
Params
|
|||
|
|
|||
|
```
|
|||
|
{
|
|||
|
“accept”: [“Spain”, “Germany”]
|
|||
|
“reject”: [“Japan”]
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### Range filter
|
|||
|
|
|||
|
Allows to remove results that don’t satisfy numeric min and max values.
|
|||
|
Filter is applied to a numeric column.
|
|||
|
|
|||
|
Params
|
|||
|
|
|||
|
```
|
|||
|
{
|
|||
|
“min”: 0,
|
|||
|
“max”: 1000
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## 3.2. How to apply filters
|
|||
|
|
|||
|
Filters must be applied at map instantiation time.
|
|||
|
|
|||
|
With :mapconfig as a valid MapConfig and with :filters (a valid JSON) as:
|
|||
|
|
|||
|
### Anonymous map
|
|||
|
|
|||
|
`GET /api/v1/map?config=:mapconfig&filters=:filters`
|
|||
|
|
|||
|
`POST /api/v1/map?filters=:filters`
|
|||
|
with `BODY=:mapconfig`
|
|||
|
|
|||
|
If in the future we need to support a bigger filters param and it doesn’t fit in the query string,
|
|||
|
we might solve it by accepting:
|
|||
|
|
|||
|
`POST /api/v1/map`
|
|||
|
with `BODY={“config”: :mapconfig, “filters”: :filters}`
|
|||
|
|
|||
|
### Named map
|
|||
|
|
|||
|
Assume :params (a valid JSON) as named maps params, like in: `{“color”: “red”}`
|
|||
|
|
|||
|
`GET /api/v1/named/:name/jsonp?config=:params&filters=:filters&callback=cb`
|
|||
|
|
|||
|
`POST /api/v1/named/:name?filters=:filters`
|
|||
|
with `BODY=:params`
|
|||
|
|
|||
|
If, again, in the future we need to support a bigger filters param that doesn’t fit in the query string,
|
|||
|
we might solve it by accepting:
|
|||
|
|
|||
|
`POST /api/v1/named/:name`
|
|||
|
with `BODY={“config”: :params, “filters”: :filters}`
|
|||
|
|
|||
|
|
|||
|
## 3.3 Bounding box special filter
|
|||
|
|
|||
|
A bounding box filter allows to remove results that don’t satisfy a geospatial range.
|
|||
|
|
|||
|
The bounding box special filter is available per dataview and there is no need to create a bounding box definition as
|
|||
|
it’s always possible to apply a bbox filter per dataview.
|
|||
|
|
|||
|
A dataview can get its result filtered by bounding box by sending a bbox param in the query string,
|
|||
|
param must be in the form `west,south,east,north`.
|
|||
|
|
|||
|
So applying a bbox filter to a dataview looks like:
|
|||
|
GET /api/v1/map/:layergroupid/dataview/:dataview_name?bbox=-90,-45,90,45
|
|||
|
|
|||
|
# History
|
|||
|
|
|||
|
## 1.0.0-alpha
|
|||
|
|
|||
|
- WIP document
|