Skip to content

Commit

Permalink
Support aggregationExp for Table/Query Sources (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmgaya authored Dec 26, 2024
1 parent 999ce7a commit bce115d
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/sources/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@ export type QuerySourceOptions = {
* ```
*/
queryParameters?: QueryParameters;

/**
* Comma-separated aggregation expressions. If assigned on a vector source, source is grouped by geometry and then aggregated.
*
* Example:
*
* 1 as value, avg(rev) as average_revenue
*/
aggregationExp?: string;
};

export type TableSourceOptions = {
Expand Down Expand Up @@ -178,6 +187,15 @@ export type TableSourceOptions = {
* - 4: 4096x4096
*/
tileResolution?: TileResolution;

/**
* Comma-separated aggregation expressions. If assigned on a vector source, source is grouped by geometry and then aggregated.
*
* Example:
*
* 1 as value, avg(rev) as average_revenue
*/
aggregationExp?: string;
};

export type TilesetSourceOptions = {
Expand Down
5 changes: 5 additions & 0 deletions src/sources/vector-query-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type UrlParameters = {
tileResolution?: string;
q: string;
queryParameters?: Record<string, unknown> | unknown[];
aggregationExp?: string;
};

export type VectorQuerySourceResponse = TilejsonResult &
Expand All @@ -46,6 +47,7 @@ export const vectorQuerySource = async function (
sqlQuery,
tileResolution = DEFAULT_TILE_RESOLUTION,
queryParameters,
aggregationExp,
} = options;

const urlParameters: UrlParameters = {
Expand All @@ -64,6 +66,9 @@ export const vectorQuerySource = async function (
if (queryParameters) {
urlParameters.queryParameters = queryParameters;
}
if (aggregationExp) {
urlParameters.aggregationExp = aggregationExp;
}
return baseSource<UrlParameters>('query', options, urlParameters).then(
(result) => ({
...(result as TilejsonResult),
Expand Down
6 changes: 6 additions & 0 deletions src/sources/vector-table-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ export type VectorTableSourceOptions = SourceOptions &
TableSourceOptions &
FilterOptions &
ColumnsOption;

type UrlParameters = {
columns?: string;
filters?: Record<string, unknown>;
spatialDataType: SpatialDataType;
spatialDataColumn?: string;
tileResolution?: string;
name: string;
aggregationExp?: string;
};

export type VectorTableSourceResponse = TilejsonResult &
Expand All @@ -43,6 +45,7 @@ export const vectorTableSource = async function (
spatialDataColumn = 'geom',
tableName,
tileResolution = DEFAULT_TILE_RESOLUTION,
aggregationExp,
} = options;

const urlParameters: UrlParameters = {
Expand All @@ -58,6 +61,9 @@ export const vectorTableSource = async function (
if (filters) {
urlParameters.filters = filters;
}
if (aggregationExp) {
urlParameters.aggregationExp = aggregationExp;
}
return baseSource<UrlParameters>('table', options, urlParameters).then(
(result) => ({
...(result as TilejsonResult),
Expand Down
16 changes: 16 additions & 0 deletions test/sources/vector-query-source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ describe('vectorQuerySource', () => {
columns: ['a', 'b'],
spatialDataColumn: 'mygeom',
queryParameters: {type: 'Supermarket', minRevenue: 1000000},
aggregationExp: 'SUM(revenue)',
});

expect(vi.mocked(fetch)).toHaveBeenCalledTimes(2);
Expand All @@ -51,6 +52,7 @@ describe('vectorQuerySource', () => {
expect(initURL).toMatch(/columns=a%2Cb/);
expect(initURL).toMatch(/spatialDataColumn=mygeom/);
expect(initURL).toMatch(/spatialDataType=geo/);
expect(initURL).toMatch(/aggregationExp=SUM%28revenue%29/);
expect(initURL).toMatch(
/queryParameters=%7B%22type%22%3A%22Supermarket%22%2C%22minRevenue%22%3A1000000%7D/
);
Expand All @@ -66,6 +68,20 @@ describe('vectorQuerySource', () => {
expect(tilejson.accessToken).toBe('<token>');
});

test('when aggregationExp is not provided', async () => {
await vectorQuerySource({
connectionName: 'carto_dw',
accessToken: '<token>',
sqlQuery: 'SELECT * FROM a.b.vector_table',
columns: ['a', 'b'],
spatialDataColumn: 'mygeom',
queryParameters: {type: 'Supermarket', minRevenue: 1000000},
});

const [[initURL]] = vi.mocked(fetch).mock.calls;
expect(initURL).not.toContain('aggregationExp');
});

test('widgetSource', async () => {
const {widgetSource} = await vectorQuerySource({
accessToken: '<token>',
Expand Down
16 changes: 15 additions & 1 deletion test/sources/vector-table-source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ describe('vectorTableSource', () => {
tableName: 'a.b.vector_table',
columns: ['a', 'b'],
spatialDataColumn: 'mygeom',
aggregationExp: 'SUM(revenue)',
});

expect(vi.mocked(fetch)).toHaveBeenCalledTimes(2);
Expand All @@ -50,7 +51,7 @@ describe('vectorTableSource', () => {
expect(initURL).toMatch(/columns=a%2Cb/);
expect(initURL).toMatch(/spatialDataColumn=mygeom/);
expect(initURL).toMatch(/spatialDataType=geo/);

expect(initURL).toMatch(/aggregationExp=SUM%28revenue%29/);
expect(tilesetURL).toMatch(
/^https:\/\/xyz\.com\/\?format\=tilejson\&cache\=/
);
Expand All @@ -62,6 +63,19 @@ describe('vectorTableSource', () => {
expect(tilejson.accessToken).toBe('<token>');
});

test('when aggregationExp is not provided', async () => {
await vectorTableSource({
connectionName: 'carto_dw',
accessToken: '<token>',
tableName: 'a.b.vector_table',
columns: ['a', 'b'],
spatialDataColumn: 'mygeom',
});

const [[initURL]] = vi.mocked(fetch).mock.calls;
expect(initURL).not.toContain('aggregationExp');
});

test('widgetSource', async () => {
const {widgetSource} = await vectorTableSource({
accessToken: '<token>',
Expand Down

0 comments on commit bce115d

Please sign in to comment.