From d969be2284d49e5fa45fa9e3d42be74e9c98efae Mon Sep 17 00:00:00 2001 From: ssanjay1 <67482244+ssanjay1@users.noreply.github.com> Date: Wed, 28 Feb 2024 15:31:54 -0500 Subject: [PATCH] Add numeric groupbys (#99) --- examples/basic/cli/src/index.ts | 44 ++++++++++++++++++- .../client/changelog/@unreleased/pr-99.v2.yml | 5 +++ .../modernToLegacyGroupByClause.ts | 44 ++++++++++++++----- .../src/object/aggregateOrThrow.test.ts | 44 +++++++++++++++++++ .../AggregationResultsWithGroups.ts | 10 +++-- .../src/query/aggregations/GroupByClause.ts | 6 +++ .../src/query/aggregations/GroupByMapper.ts | 11 ++++- 7 files changed, 146 insertions(+), 18 deletions(-) create mode 100644 packages/client/changelog/@unreleased/pr-99.v2.yml diff --git a/examples/basic/cli/src/index.ts b/examples/basic/cli/src/index.ts index b9e6f97ea..427e98fa7 100644 --- a/examples/basic/cli/src/index.ts +++ b/examples/basic/cli/src/index.ts @@ -200,7 +200,37 @@ async function runTests() { const testAggregateCountWithGroups = await client.objects.BoundariesUsState .aggregateOrThrow({ select: { $count: true, latitude: ["min", "max", "avg"] }, - groupBy: { usState: "exact" }, + groupBy: { + usState: "exact", + longitude: { + fixedWidth: 10, + }, + }, + }); + + const testAggregateCountWithFixedGroups = await client.objects + .BoundariesUsState + .aggregateOrThrow({ + select: { $count: true, latitude: ["min", "max", "avg"] }, + groupBy: { + longitude: { + exactWithLimit: 40, + }, + }, + }); + + const testAggregateCountWithRangeGroups = await client.objects + .BoundariesUsState + .aggregateOrThrow({ + select: { $count: true }, + groupBy: { + latitude: { + ranges: [[34, 39], [ + 39, + 42, + ], [43, 45]], + }, + }, }); console.log( @@ -211,6 +241,18 @@ async function runTests() { testAggregateCountWithGroups[0].latitude.min, ); + console.log(testAggregateCountWithGroups[0].$group.longitude); + console.log( + "Limit worked:", + testAggregateCountWithFixedGroups.length === 40, + ); + + for (const group of testAggregateCountWithRangeGroups) { + console.log( + `start:${group.$group.latitude.startValue},end:${group.$group.latitude.endValue}:${group.$count}`, + ); + } + if (runOld) await typeChecks(client); } catch (e) { console.error("Caught an error we did not expect", typeof e); diff --git a/packages/client/changelog/@unreleased/pr-99.v2.yml b/packages/client/changelog/@unreleased/pr-99.v2.yml new file mode 100644 index 000000000..9e9af2121 --- /dev/null +++ b/packages/client/changelog/@unreleased/pr-99.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: Add numeric groupbys + links: + - https://github.com/palantir/osdk-ts/pull/99 diff --git a/packages/client/src/internal/conversions/modernToLegacyGroupByClause.ts b/packages/client/src/internal/conversions/modernToLegacyGroupByClause.ts index 8893bee62..f3d52da23 100644 --- a/packages/client/src/internal/conversions/modernToLegacyGroupByClause.ts +++ b/packages/client/src/internal/conversions/modernToLegacyGroupByClause.ts @@ -14,7 +14,11 @@ * limitations under the License. */ -import type { AggregationGroupByV2 } from "@osdk/gateway/types"; +import type { + AggregationGroupByV2, + AggregationRangeV2, +} from "@osdk/gateway/types"; +import type { GroupByRange } from "../../query/aggregations/GroupByClause.js"; import type { AllGroupByValues, GroupByClause } from "../../query/index.js"; export function modernToLegacyGroupByClause( @@ -27,16 +31,32 @@ export function modernToLegacyGroupByClause( ).flatMap(([field, type]) => { if (type === "exact") { return [{ type, field }]; - } else if (type.exactWithLimit) { - return [ - { - type: "exact", - field, - maxGroupCount: type.exactWithLimit, - }, - ]; - } else { - return []; - } + } else if ("exactWithLimit" in type) { + { + return [ + { + type: "exact", + field, + maxGroupCount: type.exactWithLimit, + }, + ]; + } + } else if ("fixedWidth" in type) { + return [{ + type: "fixedWidth", + field, + fixedWidth: type.fixedWidth, + }]; + } else if ("ranges" in type) { + return [{ + type: "ranges", + field, + ranges: type.ranges.map(range => convertRange(range)), + }]; + } else return []; }); } + +function convertRange(range: GroupByRange): AggregationRangeV2 { + return { startValue: range[0], endValue: range[1] }; +} diff --git a/packages/client/src/object/aggregateOrThrow.test.ts b/packages/client/src/object/aggregateOrThrow.test.ts index 8172ac75e..34aae194a 100644 --- a/packages/client/src/object/aggregateOrThrow.test.ts +++ b/packages/client/src/object/aggregateOrThrow.test.ts @@ -36,6 +36,21 @@ interface TodoDef extends ObjectTypeDefinition<"Todo"> { id: { type: "double"; }; + intProp: { + type: "integer"; + }; + floatProp: { + type: "float"; + }; + shortProp: { + type: "short"; + }; + byteProp: { + type: "byte"; + }; + decimalProp: { + type: "decimal"; + }; priority: { type: "double"; }; @@ -61,6 +76,21 @@ const Todo: TodoDef = { priority: { type: "double", }, + intProp: { + type: "integer", + }, + floatProp: { + type: "float", + }, + shortProp: { + type: "short", + }, + byteProp: { + type: "byte", + }, + decimalProp: { + type: "decimal", + }, other: { type: "string", }, @@ -173,13 +203,27 @@ describe("aggregateOrThrow", () => { }, groupBy: { text: "exact", + priority: { exactWithLimit: 10 }, + intProp: { ranges: [[1, 2]] }, + shortProp: { + ranges: [[2, 3], [4, 5]], + }, + floatProp: { fixedWidth: 10 }, }, }, ); expectType>(grouped); expectType(grouped[0].$group.text); expectType(grouped[0].id.approximateDistinct); + expectType(grouped[0].$group.priority); expectType(grouped[0].$count); + expectType<{ startValue: number; endValue: number }>( + grouped[0].$group.intProp, + ); + expectType<{ startValue: number; endValue: number }>( + grouped[0].$group.shortProp, + ); + expectType(grouped[0].$group.floatProp); }); it("works with where: todo", async () => { diff --git a/packages/client/src/query/aggregations/AggregationResultsWithGroups.ts b/packages/client/src/query/aggregations/AggregationResultsWithGroups.ts index f955c4ac2..15c10ed24 100644 --- a/packages/client/src/query/aggregations/AggregationResultsWithGroups.ts +++ b/packages/client/src/query/aggregations/AggregationResultsWithGroups.ts @@ -21,7 +21,7 @@ import type { AggregationResultsWithoutGroups, } from "./AggregationResultsWithoutGroups.js"; import type { AggregationClause } from "./AggregationsClause.js"; -import type { GroupByClause } from "./GroupByClause.js"; +import type { GroupByClause, GroupByRange } from "./GroupByClause.js"; export type AggregationResultsWithGroups< Q extends ObjectOrInterfaceDefinition, @@ -30,9 +30,11 @@ export type AggregationResultsWithGroups< > = ( & { $group: { - [P in keyof G & keyof Q["properties"]]: OsdkObjectPropertyType< - Q["properties"][P] - >; + [P in keyof G & keyof Q["properties"]]: G[P] extends + { ranges: GroupByRange[] } ? { startValue: number; endValue: number } + : OsdkObjectPropertyType< + Q["properties"][P] + >; }; } & AggregationCountResult diff --git a/packages/client/src/query/aggregations/GroupByClause.ts b/packages/client/src/query/aggregations/GroupByClause.ts index 243760632..370e12b53 100644 --- a/packages/client/src/query/aggregations/GroupByClause.ts +++ b/packages/client/src/query/aggregations/GroupByClause.ts @@ -25,6 +25,12 @@ export type GroupByClause< }; export type StringGroupByValue = "exact" | { exactWithLimit: number }; +export type GroupByRange = [number, number]; + +export type NumericGroupByValue = "exact" | { exactWithLimit: number } | { + fixedWidth: number; +} | { ranges: GroupByRange[] }; + type GroupByEntry< Q extends ObjectOrInterfaceDefinition, P extends AggregatableKeys, diff --git a/packages/client/src/query/aggregations/GroupByMapper.ts b/packages/client/src/query/aggregations/GroupByMapper.ts index bf9b7361e..7dc6032bd 100644 --- a/packages/client/src/query/aggregations/GroupByMapper.ts +++ b/packages/client/src/query/aggregations/GroupByMapper.ts @@ -14,8 +14,17 @@ * limitations under the License. */ -import type { StringGroupByValue } from "./GroupByClause.js"; +import type { + NumericGroupByValue, + StringGroupByValue, +} from "./GroupByClause.js"; export interface GroupByMapper { string: StringGroupByValue; + short: NumericGroupByValue; + float: NumericGroupByValue; + decimal: NumericGroupByValue; + byte: NumericGroupByValue; + double: NumericGroupByValue; + integer: NumericGroupByValue; }