Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,8 @@ export function getFlattenedFields(obj: EsDocSource, resultsField: string): EsFi

export const getDefaultFieldsFromJobCaps = (
fields: Field[],
jobConfig: DataFrameAnalyticsConfig
jobConfig: DataFrameAnalyticsConfig,
needsDestIndexFields: boolean
): { selectedFields: Field[]; docFields: Field[]; depVarType?: ES_FIELD_TYPES } => {
const fieldsObj = { selectedFields: [], docFields: [] };
if (fields.length === 0) {
Expand All @@ -260,16 +261,22 @@ export const getDefaultFieldsFromJobCaps = (
const predictedField = `${resultsField}.${
predictionFieldName ? predictionFieldName : defaultPredictionField
}`;

const allFields: any = [
{
id: `${resultsField}.is_training`,
name: `${resultsField}.is_training`,
type: ES_FIELD_TYPES.BOOLEAN,
},
{ id: predictedField, name: predictedField, type },
...fields,
].sort(({ name: a }, { name: b }) => sortRegressionResultsFields(a, b, jobConfig));
// Only need to add these first two fields if we didn't use dest index pattern to get the fields
const allFields: any =
needsDestIndexFields === true
? [
{
id: `${resultsField}.is_training`,
name: `${resultsField}.is_training`,
type: ES_FIELD_TYPES.BOOLEAN,
},
{ id: predictedField, name: predictedField, type },
]
: [];

allFields.push(...fields);
// @ts-ignore
allFields.sort(({ name: a }, { name: b }) => sortRegressionResultsFields(a, b, jobConfig));

let selectedFields = allFields
.slice(0, DEFAULT_REGRESSION_COLUMNS * 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/
import { ResultsSearchQuery, defaultSearchQuery } from '../../../../common/analytics';
import { LoadingPanel } from '../loading_panel';
import { getIndexPatternIdFromName } from '../../../../../util/index_utils';
import { IIndexPattern } from '../../../../../../../../../../src/plugins/data/common/index_patterns';
import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public';
import { newJobCapsService } from '../../../../../services/new_job_capabilities_service';
import { useMlContext } from '../../../../../contexts/ml';
import { isGetDataFrameAnalyticsStatsResponseOk } from '../../../analytics_management/services/analytics_service/get_analytics';
Expand Down Expand Up @@ -53,6 +53,7 @@ interface Props {
export const ClassificationExploration: FC<Props> = ({ jobId }) => {
const [jobConfig, setJobConfig] = useState<DataFrameAnalyticsConfig | undefined>(undefined);
const [jobStatus, setJobStatus] = useState<DATA_FRAME_TASK_STATE | undefined>(undefined);
const [indexPattern, setIndexPattern] = useState<IndexPattern | undefined>(undefined);
const [isLoadingJobConfig, setIsLoadingJobConfig] = useState<boolean>(false);
const [isInitialized, setIsInitialized] = useState<boolean>(false);
const [jobConfigErrorMessage, setJobConfigErrorMessage] = useState<undefined | string>(undefined);
Expand Down Expand Up @@ -108,11 +109,27 @@ export const ClassificationExploration: FC<Props> = ({ jobId }) => {
const initializeJobCapsService = async () => {
if (jobConfig !== undefined) {
try {
const sourceIndex = jobConfig.source.index[0];
const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
const indexPattern: IIndexPattern = await mlContext.indexPatterns.get(indexPatternId);
if (indexPattern !== undefined) {
await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false);
const destIndex = Array.isArray(jobConfig.dest.index)
? jobConfig.dest.index[0]
: jobConfig.dest.index;
const destIndexPatternId = getIndexPatternIdFromName(destIndex) || destIndex;
let indexP: IndexPattern | undefined;

try {
indexP = await mlContext.indexPatterns.get(destIndexPatternId);
} catch (e) {
indexP = undefined;
}

if (indexP === undefined) {
const sourceIndex = jobConfig.source.index[0];
const sourceIndexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
indexP = await mlContext.indexPatterns.get(sourceIndexPatternId);
}

if (indexP !== undefined) {
setIndexPattern(indexP);
await newJobCapsService.initializeFromIndexPattern(indexP, false, false);
}
setIsInitialized(true);
} catch (e) {
Expand All @@ -127,7 +144,7 @@ export const ClassificationExploration: FC<Props> = ({ jobId }) => {

useEffect(() => {
initializeJobCapsService();
}, [JSON.stringify(jobConfig)]);
}, [jobConfig && jobConfig.id]);

if (jobConfigErrorMessage !== undefined || jobCapsServiceErrorMessage !== undefined) {
return (
Expand All @@ -153,13 +170,17 @@ export const ClassificationExploration: FC<Props> = ({ jobId }) => {
)}
<EuiSpacer />
{isLoadingJobConfig === true && jobConfig === undefined && <LoadingPanel />}
{isLoadingJobConfig === false && jobConfig !== undefined && isInitialized === true && (
<ResultsTable
jobConfig={jobConfig}
jobStatus={jobStatus}
setEvaluateSearchQuery={setSearchQuery}
/>
)}
{isLoadingJobConfig === false &&
jobConfig !== undefined &&
indexPattern !== undefined &&
isInitialized === true && (
<ResultsTable
jobConfig={jobConfig}
indexPattern={indexPattern}
jobStatus={jobStatus}
setEvaluateSearchQuery={setSearchQuery}
/>
)}
</Fragment>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {

import { Query as QueryType } from '../../../analytics_management/components/analytics_list/common';
import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public';
import { mlFieldFormatService } from '../../../../../services/field_format_service';
import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public';

import {
ColumnType,
Expand Down Expand Up @@ -61,7 +63,6 @@ import {
} from '../../../../common';
import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns';
import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';

import { useExploreData, TableItem } from './use_explore_data';
import { ExplorationTitle } from './classification_exploration';

Expand All @@ -85,13 +86,14 @@ const showingFirstDocs = i18n.translate(
);

interface Props {
indexPattern: IndexPattern;
jobConfig: DataFrameAnalyticsConfig;
jobStatus?: DATA_FRAME_TASK_STATE;
setEvaluateSearchQuery: React.Dispatch<React.SetStateAction<object>>;
}

export const ResultsTable: FC<Props> = React.memo(
({ jobConfig, jobStatus, setEvaluateSearchQuery }) => {
({ indexPattern, jobConfig, jobStatus, setEvaluateSearchQuery }) => {
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(25);
const [selectedFields, setSelectedFields] = useState([] as Field[]);
Expand Down Expand Up @@ -126,19 +128,33 @@ export const ResultsTable: FC<Props> = React.memo(
}
}

const needsDestIndexFields = indexPattern && indexPattern.title === jobConfig.source.index[0];

const {
errorMessage,
loadExploreData,
sortField,
sortDirection,
status,
tableItems,
} = useExploreData(jobConfig, selectedFields, setSelectedFields, setDocFields, setDepVarType);
} = useExploreData(
jobConfig,
needsDestIndexFields,
selectedFields,
setSelectedFields,
setDocFields,
setDepVarType
);

const columns: Array<ColumnType<TableItem>> = selectedFields
.sort(({ name: a }, { name: b }) => sortRegressionResultsFields(a, b, jobConfig))
.map(field => {
const { type } = field;
let format: any;

if (indexPattern !== undefined) {
format = mlFieldFormatService.getFieldFormatFromIndexPattern(indexPattern, field.id, '');
}
const isNumber =
type !== undefined &&
(BASIC_NUMERICAL_TYPES.has(type) || EXTENDED_NUMERICAL_TYPES.has(type));
Expand All @@ -151,6 +167,11 @@ export const ResultsTable: FC<Props> = React.memo(
};

const render = (d: any, fullItem: EsDoc) => {
if (format !== undefined) {
d = format.convert(d, 'text');
return d;
}

if (Array.isArray(d) && d.every(item => typeof item === 'string')) {
// If the cells data is an array of strings, return as a comma separated list.
// The list will get limited to 5 items with `…` at the end if there's more in the original array.
Expand Down Expand Up @@ -193,12 +214,16 @@ export const ResultsTable: FC<Props> = React.memo(
break;
case ES_FIELD_TYPES.DATE:
column.align = 'right';
column.render = (d: any) => {
if (d !== undefined) {
return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000);
}
return d;
};
if (format !== undefined) {
column.render = render;
} else {
column.render = (d: any) => {
if (d !== undefined) {
return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000);
}
return d;
};
}
break;
default:
column.render = render;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface UseExploreDataReturnType {

export const useExploreData = (
jobConfig: DataFrameAnalyticsConfig | undefined,
needsDestIndexFields: boolean,
selectedFields: Field[],
setSelectedFields: React.Dispatch<React.SetStateAction<Field[]>>,
setDocFields: React.Dispatch<React.SetStateAction<Field[]>>,
Expand All @@ -70,7 +71,7 @@ export const useExploreData = (
selectedFields: defaultSelected,
docFields,
depVarType,
} = getDefaultFieldsFromJobCaps(fields, jobConfig);
} = getDefaultFieldsFromJobCaps(fields, jobConfig, needsDestIndexFields);

setDepVarType(depVarType);
setSelectedFields(defaultSelected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { EuiDataGrid, EuiDataGridPaginationProps, EuiDataGridSorting } from '@el

import { euiDataGridStyle, euiDataGridToolbarSettings } from '../../../../common';

import { mlFieldFormatService } from '../../../../../services/field_format_service';

import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public';

const FEATURE_INFLUENCE = 'feature_influence';
const PAGE_SIZE_OPTIONS = [5, 10, 25, 50];

Expand All @@ -21,6 +25,7 @@ type TableItem = Record<string, any>;
interface ExplorationDataGridProps {
colorRange: (d: number) => string;
columns: any[];
indexPattern: IndexPattern;
pagination: Pagination;
resultsField: string;
rowCount: number;
Expand All @@ -35,6 +40,7 @@ interface ExplorationDataGridProps {
export const ExplorationDataGrid: FC<ExplorationDataGridProps> = ({
colorRange,
columns,
indexPattern,
pagination,
resultsField,
rowCount,
Expand Down Expand Up @@ -63,6 +69,12 @@ export const ExplorationDataGrid: FC<ExplorationDataGridProps> = ({
return null;
}

let format: any;

if (indexPattern !== undefined) {
format = mlFieldFormatService.getFieldFormatFromIndexPattern(indexPattern, columnId, '');
}

const cellValue =
fullItem.hasOwnProperty(columnId) && fullItem[columnId] !== undefined
? fullItem[columnId]
Expand All @@ -87,6 +99,10 @@ export const ExplorationDataGrid: FC<ExplorationDataGridProps> = ({
});
}

if (format !== undefined) {
return format.convert(cellValue, 'text');
}

if (typeof cellValue === 'string' || cellValue === null) {
return cellValue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export const OutlierExploration: FC<ExplorationProps> = React.memo(({ jobId }) =
<ExplorationDataGrid
colorRange={colorRange}
columns={columns}
indexPattern={indexPattern}
pagination={pagination}
resultsField={jobConfig.dest.results_field}
rowCount={rowCount}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ interface Props {
export const RegressionExploration: FC<Props> = ({ jobId }) => {
const [jobConfig, setJobConfig] = useState<DataFrameAnalyticsConfig | undefined>(undefined);
const [jobStatus, setJobStatus] = useState<DATA_FRAME_TASK_STATE | undefined>(undefined);
const [indexPattern, setIndexPattern] = useState<any | undefined>(undefined);
const [isLoadingJobConfig, setIsLoadingJobConfig] = useState<boolean>(false);
const [isInitialized, setIsInitialized] = useState<boolean>(false);
const [jobConfigErrorMessage, setJobConfigErrorMessage] = useState<undefined | string>(undefined);
Expand Down Expand Up @@ -99,11 +100,27 @@ export const RegressionExploration: FC<Props> = ({ jobId }) => {
const initializeJobCapsService = async () => {
if (jobConfig !== undefined) {
try {
const sourceIndex = jobConfig.source.index[0];
const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
const indexPattern: IIndexPattern = await mlContext.indexPatterns.get(indexPatternId);
if (indexPattern !== undefined) {
await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false);
const destIndex = Array.isArray(jobConfig.dest.index)
? jobConfig.dest.index[0]
: jobConfig.dest.index;
const destIndexPatternId = getIndexPatternIdFromName(destIndex) || destIndex;
let indexP: IIndexPattern | undefined;

try {
indexP = await mlContext.indexPatterns.get(destIndexPatternId);
} catch (e) {
indexP = undefined;
}

if (indexP === undefined) {
const sourceIndex = jobConfig.source.index[0];
const sourceIndexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
indexP = await mlContext.indexPatterns.get(sourceIndexPatternId);
}

if (indexP !== undefined) {
setIndexPattern(indexP);
await newJobCapsService.initializeFromIndexPattern(indexP, false, false);
}
setIsInitialized(true);
} catch (e) {
Expand All @@ -118,7 +135,7 @@ export const RegressionExploration: FC<Props> = ({ jobId }) => {

useEffect(() => {
initializeJobCapsService();
}, [JSON.stringify(jobConfig)]);
}, [jobConfig && jobConfig.id]);

if (jobConfigErrorMessage !== undefined || jobCapsServiceErrorMessage !== undefined) {
return (
Expand All @@ -144,13 +161,17 @@ export const RegressionExploration: FC<Props> = ({ jobId }) => {
)}
<EuiSpacer />
{isLoadingJobConfig === true && jobConfig === undefined && <LoadingPanel />}
{isLoadingJobConfig === false && jobConfig !== undefined && isInitialized === true && (
<ResultsTable
jobConfig={jobConfig}
jobStatus={jobStatus}
setEvaluateSearchQuery={setSearchQuery}
/>
)}
{isLoadingJobConfig === false &&
jobConfig !== undefined &&
indexPattern !== undefined &&
isInitialized === true && (
<ResultsTable
jobConfig={jobConfig}
indexPattern={indexPattern}
jobStatus={jobStatus}
setEvaluateSearchQuery={setSearchQuery}
/>
)}
</Fragment>
);
};
Loading