diff --git a/x-pack/plugins/ml/common/util/fields_utils.ts b/x-pack/plugins/ml/common/util/fields_utils.ts index f17a593dd09dc..9e0806069a9d3 100644 --- a/x-pack/plugins/ml/common/util/fields_utils.ts +++ b/x-pack/plugins/ml/common/util/fields_utils.ts @@ -60,7 +60,9 @@ export function combineFieldsAndAggs( default: // all other aggs take numerical fields numericalFields.forEach((f) => { - mix(f, a); + if (f.aggregatable) { + mix(f, a); + } }); break; } diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts index 4e52a0ddee38d..83144d20b39bc 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts @@ -10,7 +10,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { IScopedClusterClient } from '@kbn/core/server'; import { ES_FIELD_TYPES } from '@kbn/field-types'; import type { DataViewsService } from '@kbn/data-views-plugin/common'; -import type { Field, FieldId, NewJobCaps, RollupFields } from '../../../../common/types/fields'; +import type { Field, NewJobCaps, RollupFields } from '../../../../common/types/fields'; import { combineFieldsAndAggs } from '../../../../common/util/fields_utils'; import { rollupServiceProvider } from './rollup'; import { aggregations, mlOnlyAggregations } from '../../../../common/constants/aggregation_types'; @@ -62,7 +62,7 @@ class FieldsService { this._dataViewsService = dataViewsService; } - private async loadFieldCaps(): Promise { + private async loadFieldCaps() { return await this._mlClusterClient.asCurrentUser.fieldCaps( { index: this._indexPattern, @@ -77,7 +77,7 @@ class FieldsService { const fieldCaps = await this.loadFieldCaps(); const fields: Field[] = []; if (fieldCaps && fieldCaps.fields) { - Object.keys(fieldCaps.fields).forEach((k: FieldId) => { + Object.keys(fieldCaps.fields).forEach((k) => { const fc = fieldCaps.fields[k]; const firstKey = Object.keys(fc)[0]; if (firstKey !== undefined) { @@ -90,8 +90,8 @@ class FieldsService { fields.push({ id: k, name: k, - type: field.type, - aggregatable: field.aggregatable, + type: field.type as ES_FIELD_TYPES, + aggregatable: this.isFieldAggregatable(field), aggs: [], }); } @@ -101,6 +101,13 @@ class FieldsService { return fields.sort((a, b) => a.id.localeCompare(b.id)); } + // check to see whether the field is aggregatable + // If it is a counter field from a time series data stream, we cannot currently + // support any aggregations and so it cannot be used as a field_name in a detector. + private isFieldAggregatable(field: estypes.FieldCapsFieldCapability) { + return field.time_series_metric !== 'counter' ?? field.aggregatable; + } + // public function to load fields from _field_caps and create a list // of aggregations and fields that can be used for an ML job // if the index is a rollup, the fields and aggs will be filtered