[ML] Transforms: Fix handling of fields with keyword mapping available (#98882)

- For groupby/agg configs, removes the .keyword postfix for the agg name and field name being displayed. The config itself will still use the field name including .keyword.
- For histogram charts, if available, query data using the .keyword field. This enables support for charts for terms when there's both a text and keyword variant.
- Fixes isKeywordDuplicate check for field names with multiple dots in them.
This commit is contained in:
Walter Rafelsberger 2021-05-04 16:21:27 +02:00 committed by GitHub
parent bc352c033c
commit dfcb1794d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 203 additions and 34 deletions

View file

@ -0,0 +1,59 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { hasKeywordDuplicate, isKeywordDuplicate, removeKeywordPostfix } from './field_utils';
const allFields = new Set([
'field1',
'field2',
'field2.keyword',
'field3.keyword',
'field3.keyword.keyword',
'field4.keyword.b',
'field4.keyword.b.keyword',
]);
describe('field_utils: hasKeywordDuplicate()', () => {
it('returns true when a corresponding keyword field is available', () => {
expect(hasKeywordDuplicate('field2', allFields)).toBe(true);
expect(hasKeywordDuplicate('field3.keyword', allFields)).toBe(true);
expect(hasKeywordDuplicate('field4.keyword.b', allFields)).toBe(true);
});
it('returns false when a corresponding keyword field is not available', () => {
expect(hasKeywordDuplicate('field1', allFields)).toBe(false);
expect(hasKeywordDuplicate('field2.keyword', allFields)).toBe(false);
expect(hasKeywordDuplicate('field3.keyword.keyword', allFields)).toBe(false);
expect(hasKeywordDuplicate('field4.keyword.b.keyword', allFields)).toBe(false);
});
});
describe('field_utils: isKeywordDuplicate()', () => {
it('returns true when a corresponding field without keyword postfix is available', () => {
expect(isKeywordDuplicate('field2.keyword', allFields)).toBe(true);
expect(isKeywordDuplicate('field3.keyword.keyword', allFields)).toBe(true);
expect(isKeywordDuplicate('field4.keyword.b.keyword', allFields)).toBe(true);
});
it('returns false when a corresponding field without keyword postfix is not available', () => {
expect(isKeywordDuplicate('field1', allFields)).toBe(false);
expect(isKeywordDuplicate('field2', allFields)).toBe(false);
expect(isKeywordDuplicate('field3.keyword', allFields)).toBe(false);
expect(isKeywordDuplicate('field4.keyword.b', allFields)).toBe(false);
});
});
describe('field_utils: removeKeywordPostfix()', () => {
it('removes the keyword postfix', () => {
expect(removeKeywordPostfix('field2.keyword')).toBe('field2');
expect(removeKeywordPostfix('field3.keyword.keyword')).toBe('field3.keyword');
expect(removeKeywordPostfix('field4.keyword.b.keyword')).toBe('field4.keyword.b');
});
it("returns the field name as is when there's no keyword postfix", () => {
expect(removeKeywordPostfix('field1')).toBe('field1');
expect(removeKeywordPostfix('field2')).toBe('field2');
expect(removeKeywordPostfix('field4.keyword.b')).toBe('field4.keyword.b');
});
});

View file

@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export const KEYWORD_POSTFIX = '.keyword';
// checks if fieldName has a `fieldName.keyword` equivalent in the set of all field names.
export const hasKeywordDuplicate = (fieldName: string, fieldNamesSet: Set<string>): boolean =>
fieldNamesSet.has(`${fieldName}${KEYWORD_POSTFIX}`);
// checks if a fieldName ends with `.keyword` and has a field name equivalent without the postfix in the set of all field names.
export const isKeywordDuplicate = (fieldName: string, fieldNamesSet: Set<string>): boolean =>
fieldName.endsWith(KEYWORD_POSTFIX) && fieldNamesSet.has(removeKeywordPostfix(fieldName));
// removes the `.keyword` postfix form a field name if applicable
export const removeKeywordPostfix = (fieldName: string): string =>
fieldName.replace(new RegExp(`${KEYWORD_POSTFIX}$`), '');