Skip to content

Commit

Permalink
[ML] Fix race condition when loading index data. Clean up legacy outl…
Browse files Browse the repository at this point in the history
…ier influence code.
  • Loading branch information
walterra committed Oct 20, 2020
1 parent e1bd1e8 commit de33e97
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {

import {
FEATURE_IMPORTANCE,
FEATURE_INFLUENCE,
OUTLIER_SCORE,
TOP_CLASSES,
} from '../../data_frame_analytics/common/constants';
Expand Down Expand Up @@ -112,10 +111,7 @@ export const getDataGridSchemasFromFieldTypes = (fieldTypes: FieldTypes, results
schema = NON_AGGREGATABLE;
}

if (
field === `${resultsField}.${OUTLIER_SCORE}` ||
field.includes(`${resultsField}.${FEATURE_INFLUENCE}`)
) {
if (field === `${resultsField}.${OUTLIER_SCORE}`) {
schema = 'numeric';
}

Expand Down Expand Up @@ -203,11 +199,6 @@ export const useRenderCellValue = (
}

function getCellValue(cId: string) {
if (cId.includes(`.${FEATURE_INFLUENCE}.`) && resultsField !== undefined) {
const results = getNestedProperty(tableItems[adjustedRowIndex], resultsField, null);
return results[cId.replace(`${resultsField}.`, '')];
}

if (tableItems.hasOwnProperty(adjustedRowIndex)) {
const item = tableItems[adjustedRowIndex];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/public';
import { newJobCapsService } from '../../services/new_job_capabilities_service';

import { FEATURE_IMPORTANCE, FEATURE_INFLUENCE, OUTLIER_SCORE, TOP_CLASSES } from './constants';
import { FEATURE_IMPORTANCE, OUTLIER_SCORE, TOP_CLASSES } from './constants';
import { DataFrameAnalyticsConfig } from '../../../../common/types/data_frame_analytics';

export type EsId = string;
Expand Down Expand Up @@ -179,7 +179,6 @@ export const getDefaultFieldsFromJobCaps = (
const resultsField = jobConfig.dest.results_field;

const featureImportanceFields = [];
const featureInfluenceFields = [];
const topClassesFields = [];
const allFields: any = [];
let type: ES_FIELD_TYPES | undefined;
Expand All @@ -193,16 +192,6 @@ export const getDefaultFieldsFromJobCaps = (
name: `${resultsField}.${OUTLIER_SCORE}`,
type: KBN_FIELD_TYPES.NUMBER,
});

featureInfluenceFields.push(
...fields
.filter((d) => !jobConfig.analyzed_fields.excludes.includes(d.id))
.map((d) => ({
id: `${resultsField}.${FEATURE_INFLUENCE}.${d.id}`,
name: `${resultsField}.${FEATURE_INFLUENCE}.${d.name}`,
type: KBN_FIELD_TYPES.NUMBER,
}))
);
}
}

Expand Down Expand Up @@ -247,12 +236,7 @@ export const getDefaultFieldsFromJobCaps = (
}
}

allFields.push(
...fields,
...featureImportanceFields,
...featureInfluenceFields,
...topClassesFields
);
allFields.push(...fields, ...featureImportanceFields, ...topClassesFields);
allFields.sort(({ name: a }: { name: string }, { name: b }: { name: string }) =>
sortExplorationResultsFields(a, b, jobConfig)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import { DataFrameAnalyticsConfig } from '../../../../common/types/data_frame_an
export const getIndexData = async (
jobConfig: DataFrameAnalyticsConfig | undefined,
dataGrid: UseDataGridReturnType,
searchQuery: SavedSearchQuery
searchQuery: SavedSearchQuery,
options: { didCancel: boolean }
) => {
if (jobConfig !== undefined) {
const {
Expand Down Expand Up @@ -52,22 +53,19 @@ export const getIndexData = async (
index: jobConfig.dest.index,
body: {
fields: ['*'],
_source: jobConfig.dest.results_field,
_source: [],
query: searchQuery,
from: pageIndex * pageSize,
size: pageSize,
...(Object.keys(sort).length > 0 ? { sort } : {}),
},
});

setRowCount(resp.hits.total.value);
const docs = resp.hits.hits.map((d) => ({
...getProcessedFields(d.fields),
[jobConfig.dest.results_field]: d._source[jobConfig.dest.results_field],
}));

setTableItems(docs);
setStatus(INDEX_STATUS.LOADED);
if (!options.didCancel) {
setRowCount(resp.hits.total.value);
setTableItems(resp.hits.hits.map((d) => getProcessedFields(d.fields)));
setStatus(INDEX_STATUS.LOADED);
}
} catch (e) {
setErrorMessage(extractErrorMessage(e));
setStatus(INDEX_STATUS.ERROR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@ export const getFeatureCount = (resultsField: string, tableItems: DataGridItem[]

const fullItem = tableItems[0];

if (
fullItem[resultsField] !== undefined &&
Array.isArray(fullItem[resultsField][FEATURE_INFLUENCE])
) {
return fullItem[resultsField][FEATURE_INFLUENCE].length;
if (Array.isArray(fullItem[`${resultsField}.${FEATURE_INFLUENCE}.feature_name`])) {
return fullItem[`${resultsField}.${FEATURE_INFLUENCE}.feature_name`].length;
}

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,8 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =

const { columnsWithCharts, tableItems } = outlierData;

const colorRange = useColorRange(
COLOR_RANGE.BLUE,
COLOR_RANGE_SCALE.INFLUENCER,
jobConfig !== undefined ? getFeatureCount(jobConfig.dest.results_field, tableItems) : 1
);
const featureCount = getFeatureCount(jobConfig?.dest?.results_field || '', tableItems);
const colorRange = useColorRange(COLOR_RANGE.BLUE, COLOR_RANGE_SCALE.INFLUENCER, featureCount);

return (
<>
Expand All @@ -59,7 +56,7 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
)}
{typeof jobConfig?.id === 'string' && <ExpandableSectionAnalytics jobId={jobConfig?.id} />}
<ExpandableSectionResults
colorRange={colorRange}
colorRange={featureCount > 0 ? colorRange : undefined}
indexData={outlierData}
indexPattern={indexPattern}
jobConfig={jobConfig}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ import {

import { getFeatureCount, getOutlierScoreFieldName } from './common';

interface FeatureInfluence {
feature_name: string;
influence: number;
}

export const useOutlierData = (
indexPattern: IndexPattern | undefined,
jobConfig: DataFrameAnalyticsConfig | undefined,
Expand Down Expand Up @@ -88,8 +83,15 @@ export const useOutlierData = (
}
}, [jobConfig && jobConfig.id]);

// The pattern using `didCancel` allows us to abort out of date remote request.
// We wrap `didCancel` in a object so we can mutate the value as it's being
// passed on to `getIndexData`.
useEffect(() => {
getIndexData(jobConfig, dataGrid, searchQuery);
const options = { didCancel: false };
getIndexData(jobConfig, dataGrid, searchQuery, options);
return () => {
options.didCancel = true;
};
// custom comparison
}, [jobConfig && jobConfig.id, dataGrid.pagination, searchQuery, dataGrid.sortingColumns]);

Expand Down Expand Up @@ -151,19 +153,17 @@ export const useOutlierData = (
const split = columnId.split('.');
let backgroundColor;

const featureNames = fullItem[`${resultsField}.${FEATURE_INFLUENCE}.feature_name`];

// column with feature values get color coded by its corresponding influencer value
if (
fullItem[resultsField] !== undefined &&
fullItem[resultsField][FEATURE_INFLUENCE] !== undefined &&
fullItem[resultsField][FEATURE_INFLUENCE].find(
(d: FeatureInfluence) => d.feature_name === columnId
) !== undefined
) {
backgroundColor = colorRange(
fullItem[resultsField][FEATURE_INFLUENCE].find(
(d: FeatureInfluence) => d.feature_name === columnId
).influence
);
if (Array.isArray(featureNames)) {
const featureIndex = featureNames.indexOf(columnId);

if (featureIndex > -1) {
backgroundColor = colorRange(
fullItem[`${resultsField}.${FEATURE_INFLUENCE}.influence`][featureIndex]
);
}
}

// column with influencer values get color coded by its own value
Expand Down

0 comments on commit de33e97

Please sign in to comment.