Transformations: Use field name matcher for finding group by fields (#104664)

Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
Kristina
2025-04-30 05:00:43 +03:00
committed by GitHub
co-authored by Leon Sorokin
parent 6d1f918150
commit d739481c9a
2 changed files with 64 additions and 10 deletions
@@ -461,4 +461,50 @@ describe('GroupBy transformer', () => {
expect(result[0].fields).toEqual(expected);
});
});
it('should match on base name if did not match on displayName', async () => {
const testSeries = toDataFrame({
name: 'A',
fields: [
{ name: 'message', type: FieldType.string, values: ['A', 'A'], config: { displayName: 'MyMessage' } },
{ name: 'values', type: FieldType.number, values: [1, 2] },
],
});
const cfg: DataTransformerConfig<GroupByTransformerOptions> = {
id: DataTransformerID.groupBy,
options: {
fields: {
message: {
operation: GroupByOperationID.groupBy,
aggregations: [],
},
values: {
operation: GroupByOperationID.aggregate,
aggregations: [ReducerID.sum],
},
},
},
};
await expect(transformDataFrame([cfg], [testSeries])).toEmitValuesWith((received) => {
const result = received[0];
const expected: Field[] = [
{
name: 'message',
type: FieldType.string,
values: ['A'],
config: { displayName: 'MyMessage' },
},
{
name: 'values (sum)',
type: FieldType.number,
values: [3],
config: {},
},
];
expect(result[0].fields).toEqual(expected);
});
});
});
@@ -4,6 +4,8 @@ import { getFieldDisplayName } from '../../field/fieldState';
import { DataFrame, Field } from '../../types/dataFrame';
import { DataTransformerInfo, TransformationApplicabilityLevels } from '../../types/transformations';
import { getFieldTypeForReducer, reduceField, ReducerID } from '../fieldReducer';
import { getFieldMatcher } from '../matchers';
import { FieldMatcherID } from '../matchers/ids';
import { DataTransformerID } from './ids';
import { findMaxFields } from './utils';
@@ -57,20 +59,31 @@ export const groupByTransformer: DataTransformerInfo<GroupByTransformerOptions>
operator: (options) => (source) =>
source.pipe(
map((data) => {
const hasValidConfig = Object.keys(options.fields).find(
(name) => options.fields[name].operation === GroupByOperationID.groupBy
);
const groupByFieldNames: string[] = [];
if (!hasValidConfig) {
for (const [k, v] of Object.entries(options.fields)) {
if (v.operation === GroupByOperationID.groupBy) {
groupByFieldNames.push(k);
}
}
if (groupByFieldNames.length === 0) {
return data;
}
const matcher = getFieldMatcher({
id: FieldMatcherID.byNames,
options: { names: groupByFieldNames },
});
const processed: DataFrame[] = [];
for (const frame of data) {
// Create a list of fields to group on
// If there are none we skip the rest
const groupByFields: Field[] = frame.fields.filter((field) => shouldGroupOnField(field, options));
const groupByFields: Field[] = frame.fields.filter((field) => matcher(field, frame, data));
if (groupByFields.length === 0) {
continue;
}
@@ -131,11 +144,6 @@ export const groupByTransformer: DataTransformerInfo<GroupByTransformerOptions>
),
};
const shouldGroupOnField = (field: Field, options: GroupByTransformerOptions): boolean => {
const fieldName = getFieldDisplayName(field);
return options?.fields[fieldName]?.operation === GroupByOperationID.groupBy;
};
const shouldCalculateField = (field: Field, options: GroupByTransformerOptions): boolean => {
const fieldName = getFieldDisplayName(field);
return (