mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[ML] Make script_fields available on dropdowns of the advanced wirzard's detectors modal. (#21205)
- If a job configuration's datafeed contains script_fields, they are now available in the field dropdowns of the advanced wizard's detector modal. - Additionally, job validation now considers script_fields and doesn't report them as non aggregatable anymore.
This commit is contained in:
parent
d933175297
commit
d4efed5842
3 changed files with 103 additions and 6 deletions
|
@ -351,6 +351,16 @@ module.controller('MlNewJob',
|
|||
});
|
||||
});
|
||||
|
||||
// Add script fields from the job configuration to $scope.fields
|
||||
// so they're available from within the dropdown in the detector modal.
|
||||
const scriptFields = Object.keys(_.get($scope.job, 'datafeed_config.script_fields', {}));
|
||||
// This type information is retrieved via fieldCaps for regular fields,
|
||||
// here we're creating a similar object so the script field is usable further on.
|
||||
const scriptType = { type: 'script_fields', searchable: false, aggregatable: true };
|
||||
scriptFields.forEach((fieldName) => {
|
||||
$scope.fields[fieldName] = scriptType;
|
||||
});
|
||||
|
||||
if (Object.keys($scope.fields).length) {
|
||||
$scope.ui.indexTextOk = true;
|
||||
}
|
||||
|
|
|
@ -325,6 +325,81 @@ describe('ML - validateJob', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('non-existent field reported as non aggregatable', () => {
|
||||
const payload = {
|
||||
job: {
|
||||
job_id: 'categorization_test',
|
||||
analysis_config: {
|
||||
bucket_span: '15m',
|
||||
detectors: [{
|
||||
function: 'count',
|
||||
partition_field_name: 'ailine'
|
||||
}],
|
||||
influencers: []
|
||||
},
|
||||
data_description: { time_field: '@timestamp' },
|
||||
datafeed_config: { indices: [] }
|
||||
},
|
||||
fields: { testField: {} }
|
||||
};
|
||||
|
||||
return validateJob(callWithRequest, payload).then(
|
||||
(messages) => {
|
||||
const ids = messages.map(m => m.id);
|
||||
expect(ids).to.eql([
|
||||
'job_id_valid',
|
||||
'detectors_function_not_empty',
|
||||
'index_fields_valid',
|
||||
'field_not_aggregatable',
|
||||
'time_field_invalid'
|
||||
]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('script field not reported as non aggregatable', () => {
|
||||
const payload = {
|
||||
job: {
|
||||
job_id: 'categorization_test',
|
||||
analysis_config: {
|
||||
bucket_span: '15m',
|
||||
detectors: [{
|
||||
function: 'count',
|
||||
partition_field_name: 'custom_script_field'
|
||||
}],
|
||||
influencers: []
|
||||
},
|
||||
data_description: { time_field: '@timestamp' },
|
||||
datafeed_config: {
|
||||
indices: [],
|
||||
script_fields: {
|
||||
custom_script_field: {
|
||||
script: {
|
||||
source: `'some script'`,
|
||||
lang: 'painless'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
fields: { testField: {} }
|
||||
};
|
||||
|
||||
return validateJob(callWithRequest, payload).then(
|
||||
(messages) => {
|
||||
const ids = messages.map(m => m.id);
|
||||
expect(ids).to.eql([
|
||||
'job_id_valid',
|
||||
'detectors_function_not_empty',
|
||||
'index_fields_valid',
|
||||
'success_cardinality',
|
||||
'time_field_invalid',
|
||||
'influencer_low_suggestion'
|
||||
]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// the following two tests validate the correct template rendering of
|
||||
// urls in messages with {{version}} in them to be replaced with the
|
||||
// specified version. (defaulting to 'current')
|
||||
|
|
|
@ -12,6 +12,18 @@ import { DataVisualizer } from '../data_visualizer';
|
|||
|
||||
import { validateJobObject } from './validate_job_object';
|
||||
|
||||
function isValidCategorizationConfig(job, fieldName) {
|
||||
return (
|
||||
typeof job.analysis_config.categorization_field_name !== 'undefined' &&
|
||||
fieldName === 'mlcategory'
|
||||
);
|
||||
}
|
||||
|
||||
function isScriptField(job, fieldName) {
|
||||
const scriptFields = Object.keys(_.get(job, 'datafeed_config.script_fields', {}));
|
||||
return scriptFields.includes(fieldName);
|
||||
}
|
||||
|
||||
// Thresholds to determine whether cardinality is
|
||||
// too high or low for certain fields analysis
|
||||
const OVER_FIELD_CARDINALITY_THRESHOLD_LOW = 10;
|
||||
|
@ -84,12 +96,12 @@ const validateFactory = (callWithRequest, job) => {
|
|||
});
|
||||
}
|
||||
} else {
|
||||
// when the job is using categorization and the field name is set to 'mlcategory',
|
||||
// then don't report the field as not being able to be aggregated.
|
||||
if (!(
|
||||
typeof job.analysis_config.categorization_field_name !== 'undefined' &&
|
||||
uniqueFieldName === 'mlcategory'
|
||||
)) {
|
||||
// only report uniqueFieldName as not aggregatable if it's not part
|
||||
// of a valid categorization configuration and if it's not a scripted field.
|
||||
if (
|
||||
!isValidCategorizationConfig(job, uniqueFieldName) &&
|
||||
!isScriptField(job, uniqueFieldName)
|
||||
) {
|
||||
messages.push({
|
||||
id: 'field_not_aggregatable',
|
||||
fieldName: uniqueFieldName
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue