[ML] DF Analytics Outlier detection results: improve handling of text fields (#55002)
* add keyword suffix to fieldName when both text and keyword * update exploration jest test
This commit is contained in:
parent
e60289f611
commit
b9814bfb76
|
@ -7,6 +7,8 @@
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
|
import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
|
||||||
|
import { KibanaContext } from '../../../../../contexts/kibana';
|
||||||
|
import { kibanaContextValueMock } from '../../../../../contexts/kibana/__mocks__/kibana_context_value';
|
||||||
|
|
||||||
jest.mock('../../../../../contexts/ui/use_ui_chrome_context');
|
jest.mock('../../../../../contexts/ui/use_ui_chrome_context');
|
||||||
jest.mock('ui/new_platform');
|
jest.mock('ui/new_platform');
|
||||||
|
@ -22,7 +24,9 @@ jest.mock('react', () => {
|
||||||
describe('Data Frame Analytics: <Exploration />', () => {
|
describe('Data Frame Analytics: <Exploration />', () => {
|
||||||
test('Minimal initialization', () => {
|
test('Minimal initialization', () => {
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<Exploration jobId="the-job-id" jobStatus={DATA_FRAME_TASK_STATE.STOPPED} />
|
<KibanaContext.Provider value={kibanaContextValueMock}>
|
||||||
|
<Exploration jobId="the-job-id" jobStatus={DATA_FRAME_TASK_STATE.STOPPED} />
|
||||||
|
</KibanaContext.Provider>
|
||||||
);
|
);
|
||||||
// Without the jobConfig being loaded, the component will just return empty.
|
// Without the jobConfig being loaded, the component will just return empty.
|
||||||
expect(wrapper.text()).toMatch('');
|
expect(wrapper.text()).toMatch('');
|
||||||
|
|
|
@ -55,6 +55,7 @@ import {
|
||||||
SEARCH_SIZE,
|
SEARCH_SIZE,
|
||||||
defaultSearchQuery,
|
defaultSearchQuery,
|
||||||
} from '../../../../common';
|
} from '../../../../common';
|
||||||
|
import { isKeywordAndTextType } from '../../../../common/fields';
|
||||||
|
|
||||||
import { getOutlierScoreFieldName } from './common';
|
import { getOutlierScoreFieldName } from './common';
|
||||||
import { useExploreData, TableItem } from './use_explore_data';
|
import { useExploreData, TableItem } from './use_explore_data';
|
||||||
|
@ -64,6 +65,10 @@ import {
|
||||||
} from '../../../analytics_management/components/analytics_list/common';
|
} from '../../../analytics_management/components/analytics_list/common';
|
||||||
import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns';
|
import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns';
|
||||||
import { SavedSearchQuery } from '../../../../../contexts/kibana';
|
import { SavedSearchQuery } from '../../../../../contexts/kibana';
|
||||||
|
import { getIndexPatternIdFromName } from '../../../../../util/index_utils';
|
||||||
|
import { IIndexPattern } from '../../../../../../../../../../../src/plugins/data/common/index_patterns';
|
||||||
|
import { newJobCapsService } from '../../../../../services/new_job_capabilities_service';
|
||||||
|
import { useKibanaContext } from '../../../../../contexts/kibana';
|
||||||
|
|
||||||
const FEATURE_INFLUENCE = 'feature_influence';
|
const FEATURE_INFLUENCE = 'feature_influence';
|
||||||
|
|
||||||
|
@ -110,6 +115,19 @@ export const Exploration: FC<Props> = React.memo(({ jobId, jobStatus }) => {
|
||||||
const [searchError, setSearchError] = useState<any>(undefined);
|
const [searchError, setSearchError] = useState<any>(undefined);
|
||||||
const [searchString, setSearchString] = useState<string | undefined>(undefined);
|
const [searchString, setSearchString] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
|
const kibanaContext = useKibanaContext();
|
||||||
|
|
||||||
|
const initializeJobCapsService = async () => {
|
||||||
|
if (jobConfig !== undefined) {
|
||||||
|
const sourceIndex = jobConfig.source.index[0];
|
||||||
|
const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
|
||||||
|
const indexPattern: IIndexPattern = await kibanaContext.indexPatterns.get(indexPatternId);
|
||||||
|
if (indexPattern !== undefined) {
|
||||||
|
await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async function() {
|
(async function() {
|
||||||
const analyticsConfigs: GetDataFrameAnalyticsResponse = await ml.dataFrameAnalytics.getDataFrameAnalytics(
|
const analyticsConfigs: GetDataFrameAnalyticsResponse = await ml.dataFrameAnalytics.getDataFrameAnalytics(
|
||||||
|
@ -124,6 +142,10 @@ export const Exploration: FC<Props> = React.memo(({ jobId, jobStatus }) => {
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
initializeJobCapsService();
|
||||||
|
}, [jobConfig && jobConfig.id]);
|
||||||
|
|
||||||
const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]);
|
const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]);
|
||||||
const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false);
|
const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false);
|
||||||
|
|
||||||
|
@ -293,10 +315,16 @@ export const Exploration: FC<Props> = React.memo(({ jobId, jobStatus }) => {
|
||||||
if (jobConfig !== undefined) {
|
if (jobConfig !== undefined) {
|
||||||
const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig);
|
const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig);
|
||||||
const outlierScoreFieldSelected = selectedFields.includes(outlierScoreFieldName);
|
const outlierScoreFieldSelected = selectedFields.includes(outlierScoreFieldName);
|
||||||
|
let requiresKeyword = false;
|
||||||
|
|
||||||
const field = outlierScoreFieldSelected ? outlierScoreFieldName : selectedFields[0];
|
const field = outlierScoreFieldSelected ? outlierScoreFieldName : selectedFields[0];
|
||||||
const direction = outlierScoreFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
|
const direction = outlierScoreFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
|
||||||
loadExploreData({ field, direction, searchQuery });
|
|
||||||
|
if (outlierScoreFieldSelected === false) {
|
||||||
|
requiresKeyword = isKeywordAndTextType(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadExploreData({ field, direction, searchQuery, requiresKeyword });
|
||||||
}
|
}
|
||||||
}, [JSON.stringify(searchQuery)]);
|
}, [JSON.stringify(searchQuery)]);
|
||||||
|
|
||||||
|
@ -307,10 +335,16 @@ export const Exploration: FC<Props> = React.memo(({ jobId, jobStatus }) => {
|
||||||
if (jobConfig !== undefined && columns.length > 0 && !selectedFields.includes(sortField)) {
|
if (jobConfig !== undefined && columns.length > 0 && !selectedFields.includes(sortField)) {
|
||||||
const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig);
|
const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig);
|
||||||
const outlierScoreFieldSelected = selectedFields.includes(outlierScoreFieldName);
|
const outlierScoreFieldSelected = selectedFields.includes(outlierScoreFieldName);
|
||||||
|
let requiresKeyword = false;
|
||||||
|
|
||||||
const field = outlierScoreFieldSelected ? outlierScoreFieldName : selectedFields[0];
|
const field = outlierScoreFieldSelected ? outlierScoreFieldName : selectedFields[0];
|
||||||
const direction = outlierScoreFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
|
const direction = outlierScoreFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
|
||||||
loadExploreData({ field, direction, searchQuery });
|
|
||||||
|
if (outlierScoreFieldSelected === false) {
|
||||||
|
requiresKeyword = isKeywordAndTextType(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadExploreData({ field, direction, searchQuery, requiresKeyword });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, [jobConfig, columns.length, sortField, sortDirection, tableItems.length]);
|
}, [jobConfig, columns.length, sortField, sortDirection, tableItems.length]);
|
||||||
|
@ -334,8 +368,17 @@ export const Exploration: FC<Props> = React.memo(({ jobId, jobStatus }) => {
|
||||||
setPageIndex(index);
|
setPageIndex(index);
|
||||||
setPageSize(size);
|
setPageSize(size);
|
||||||
|
|
||||||
if (sort.field !== sortField || sort.direction !== sortDirection) {
|
if (
|
||||||
loadExploreData({ ...sort, searchQuery });
|
(sort.field !== sortField || sort.direction !== sortDirection) &&
|
||||||
|
jobConfig !== undefined
|
||||||
|
) {
|
||||||
|
const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig);
|
||||||
|
let requiresKeyword = false;
|
||||||
|
|
||||||
|
if (outlierScoreFieldName !== sort.field) {
|
||||||
|
requiresKeyword = isKeywordAndTextType(sort.field);
|
||||||
|
}
|
||||||
|
loadExploreData({ ...sort, searchQuery, requiresKeyword });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,18 +23,12 @@ import {
|
||||||
defaultSearchQuery,
|
defaultSearchQuery,
|
||||||
SearchQuery,
|
SearchQuery,
|
||||||
} from '../../../../common';
|
} from '../../../../common';
|
||||||
|
import { LoadExploreDataArg } from '../../../../common/analytics';
|
||||||
|
|
||||||
import { getOutlierScoreFieldName } from './common';
|
import { getOutlierScoreFieldName } from './common';
|
||||||
import { SavedSearchQuery } from '../../../../../contexts/kibana';
|
|
||||||
|
|
||||||
export type TableItem = Record<string, any>;
|
export type TableItem = Record<string, any>;
|
||||||
|
|
||||||
interface LoadExploreDataArg {
|
|
||||||
field: string;
|
|
||||||
direction: SortDirection;
|
|
||||||
searchQuery: SavedSearchQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UseExploreDataReturnType {
|
export interface UseExploreDataReturnType {
|
||||||
errorMessage: string;
|
errorMessage: string;
|
||||||
loadExploreData: (arg: LoadExploreDataArg) => void;
|
loadExploreData: (arg: LoadExploreDataArg) => void;
|
||||||
|
@ -55,7 +49,12 @@ export const useExploreData = (
|
||||||
const [sortField, setSortField] = useState<string>('');
|
const [sortField, setSortField] = useState<string>('');
|
||||||
const [sortDirection, setSortDirection] = useState<SortDirection>(SORT_DIRECTION.ASC);
|
const [sortDirection, setSortDirection] = useState<SortDirection>(SORT_DIRECTION.ASC);
|
||||||
|
|
||||||
const loadExploreData = async ({ field, direction, searchQuery }: LoadExploreDataArg) => {
|
const loadExploreData = async ({
|
||||||
|
field,
|
||||||
|
direction,
|
||||||
|
searchQuery,
|
||||||
|
requiresKeyword,
|
||||||
|
}: LoadExploreDataArg) => {
|
||||||
if (jobConfig !== undefined) {
|
if (jobConfig !== undefined) {
|
||||||
setErrorMessage('');
|
setErrorMessage('');
|
||||||
setStatus(INDEX_STATUS.LOADING);
|
setStatus(INDEX_STATUS.LOADING);
|
||||||
|
@ -70,7 +69,7 @@ export const useExploreData = (
|
||||||
if (field !== undefined) {
|
if (field !== undefined) {
|
||||||
body.sort = [
|
body.sort = [
|
||||||
{
|
{
|
||||||
[field]: {
|
[`${field}${requiresKeyword ? '.keyword' : ''}`]: {
|
||||||
order: direction,
|
order: direction,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue