Transformations: Group by should not perform calculation if operation is not set to calculate (#109430)

Do not perform calculation if operation is not Calculate
This commit is contained in:
Kristina
2025-08-13 15:07:53 -05:00
committed by GitHub
parent c7e1a3d0fd
commit df70198038
2 changed files with 74 additions and 91 deletions
@@ -8,6 +8,29 @@ import { transformDataFrame } from '../transformDataFrame';
import { GroupByOperationID, groupByTransformer, GroupByTransformerOptions } from './groupBy';
import { DataTransformerID } from './ids';
// returns a simple group by / reducer pair
const getSimpleGroupByConfig = (
groupName: string,
valuesName: string,
reducer: ReducerID
): DataTransformerConfig<GroupByTransformerOptions> => {
return {
id: DataTransformerID.groupBy,
options: {
fields: {
[groupName]: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
[valuesName]: {
operation: GroupByOperationID.aggregate,
aggregations: [reducer],
},
},
},
};
};
describe('GroupBy transformer', () => {
beforeAll(() => {
mockTransformationsRegistry([groupByTransformer]);
@@ -88,21 +111,7 @@ describe('GroupBy transformer', () => {
],
});
const cfg: DataTransformerConfig<GroupByTransformerOptions> = {
id: DataTransformerID.groupBy,
options: {
fields: {
message: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
values: {
operation: GroupByOperationID.aggregate,
aggregations: [ReducerID.sum],
},
},
},
};
const cfg = getSimpleGroupByConfig('message', 'values', ReducerID.sum);
await expect(transformDataFrame([cfg], [testSeries])).toEmitValuesWith((received) => {
const result = received[0];
@@ -208,21 +217,7 @@ describe('GroupBy transformer', () => {
}),
];
const cfg: DataTransformerConfig<GroupByTransformerOptions> = {
id: DataTransformerID.groupBy,
options: {
fields: {
message: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
values: {
operation: GroupByOperationID.aggregate,
aggregations: [ReducerID.sum],
},
},
},
};
const cfg = getSimpleGroupByConfig('message', 'values', ReducerID.sum);
await expect(transformDataFrame([cfg], testSeries)).toEmitValuesWith((received) => {
const result = received[0];
@@ -270,21 +265,7 @@ describe('GroupBy transformer', () => {
],
});
const cfg: DataTransformerConfig<GroupByTransformerOptions> = {
id: DataTransformerID.groupBy,
options: {
fields: {
message: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
values: {
operation: GroupByOperationID.aggregate,
aggregations: [ReducerID.sum],
},
},
},
};
const cfg = getSimpleGroupByConfig('message', 'values', ReducerID.sum);
await expect(transformDataFrame([cfg], [testSeries])).toEmitValuesWith((received) => {
const result = received[0];
@@ -378,21 +359,7 @@ describe('GroupBy transformer', () => {
],
});
const cfg: DataTransformerConfig<GroupByTransformerOptions> = {
id: DataTransformerID.groupBy,
options: {
fields: {
user: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
time: {
operation: GroupByOperationID.aggregate,
aggregations: [ReducerID.max],
},
},
},
};
const cfg = getSimpleGroupByConfig('user', 'time', ReducerID.max);
await expect(transformDataFrame([cfg], [testSeries])).toEmitValuesWith((received) => {
const result = received[0];
@@ -425,21 +392,7 @@ describe('GroupBy transformer', () => {
],
});
const cfg: DataTransformerConfig<GroupByTransformerOptions> = {
id: DataTransformerID.groupBy,
options: {
fields: {
user: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
time: {
operation: GroupByOperationID.aggregate,
aggregations: [ReducerID.max],
},
},
},
};
const cfg = getSimpleGroupByConfig('user', 'time', ReducerID.max);
await expect(transformDataFrame([cfg], [testSeries])).toEmitValuesWith((received) => {
const result = received[0];
@@ -477,21 +430,7 @@ describe('GroupBy transformer', () => {
],
});
const cfg: DataTransformerConfig<GroupByTransformerOptions> = {
id: DataTransformerID.groupBy,
options: {
fields: {
message: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
values: {
operation: GroupByOperationID.aggregate,
aggregations: [ReducerID.sum],
},
},
},
};
const cfg = getSimpleGroupByConfig('message', 'values', ReducerID.sum);
await expect(transformDataFrame([cfg], [testSeries])).toEmitValuesWith((received) => {
const result = received[0];
@@ -513,4 +452,44 @@ describe('GroupBy transformer', () => {
expect(result[0].fields).toEqual(expected);
});
});
it('should not aggregate fields without an operation', async () => {
const testSeries = toDataFrame({
name: 'A',
fields: [
{ name: 'category', type: FieldType.string, values: ['A', 'A', 'B', 'B'], config: {} },
{ name: 'values', type: FieldType.number, values: [1, 2, 3, 4], config: {} },
],
});
// when the operation field is cleared the aggregations are kept in state in case they are needed, but they should not be used by the transformation
let cfg = {
id: DataTransformerID.groupBy,
options: {
fields: {
category: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
values: {
aggregations: [ReducerID.sum],
operation: null,
},
},
},
};
await expect(transformDataFrame([cfg], [testSeries])).toEmitValuesWith((received) => {
const result = received[0];
const expected: Field[] = [
{
name: 'category',
type: FieldType.string,
values: ['A', 'B'],
config: {},
},
];
expect(result[0].fields).toEqual(expected);
});
});
});
@@ -146,7 +146,11 @@ export const groupByTransformer: DataTransformerInfo<GroupByTransformerOptions>
const shouldCalculateField = (field: Field, options: GroupByTransformerOptions): boolean => {
const fieldName = getFieldDisplayName(field);
return Array.isArray(options?.fields[fieldName]?.aggregations) && options?.fields[fieldName].aggregations.length > 0;
return (
options?.fields[fieldName]?.operation === GroupByOperationID.aggregate &&
Array.isArray(options?.fields[fieldName]?.aggregations) &&
options?.fields[fieldName].aggregations.length > 0
);
};
/**