Skip to content

No scripted fields for significant_terms #8723

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
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 @@ -47,7 +47,8 @@ describe('Vis-Editor-Agg plugin directive', function () {
$parentScope.agg = {
id: 1,
params: {},
schema: makeConfig()
schema: makeConfig(),
getFieldOptions: () => null
};
$parentScope.groupName = 'metrics';
$parentScope.group = [{
Expand Down
29 changes: 1 addition & 28 deletions src/core_plugins/kibana/public/visualize/editor/agg_params.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ uiModules

// create child scope, used in the editors
$aggParamEditorsScope = $scope.$new();
$aggParamEditorsScope.indexedFields = $scope.agg.getFieldOptions();

const agg = $scope.agg;
if (!agg) return;
Expand All @@ -81,10 +82,6 @@ uiModules
// build collection of agg params html
type.params.forEach(function (param, i) {
let aggParam;
// if field param exists, compute allowed fields
if (param.name === 'field') {
$aggParamEditorsScope.indexedFields = getIndexedFields(param);
}

if ($aggParamEditorsScope.indexedFields) {
const hasIndexedFields = $aggParamEditorsScope.indexedFields.length > 0;
Expand Down Expand Up @@ -136,30 +133,6 @@ uiModules
.append(param.editor)
.get(0);
}

function getIndexedFields(param) {
let fields = _.filter($scope.agg.vis.indexPattern.fields.raw, 'aggregatable');
const fieldTypes = param.filterFieldTypes;

if (fieldTypes) {
fields = $filter('fieldType')(fields, fieldTypes);
fields = $filter('orderBy')(fields, ['type', 'name']);
}

return new IndexedArray({

/**
* @type {Array}
*/
index: ['name'],

/**
* [group description]
* @type {Array}
*/
initialSet: fields
});
}
}
};
});
91 changes: 60 additions & 31 deletions src/fixtures/logstash_fields.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,65 @@
function stubbedLogstashFields() {
let sourceData = [
{ name: 'bytes', type: 'number', indexed: true, analyzed: true, sortable: true, filterable: true, count: 10 },
{ name: 'ssl', type: 'boolean', indexed: true, analyzed: true, sortable: true, filterable: true, count: 20 },
{ name: '@timestamp', type: 'date', indexed: true, analyzed: true, sortable: true, filterable: true, count: 30 },
{ name: 'time', type: 'date', indexed: true, analyzed: true, sortable: true, filterable: true, count: 30 },
{ name: '@tags', type: 'string', indexed: true, analyzed: true, sortable: true, filterable: true },
{ name: 'utc_time', type: 'date', indexed: true, analyzed: true, sortable: true, filterable: true },
{ name: 'phpmemory', type: 'number', indexed: true, analyzed: true, sortable: true, filterable: true },
{ name: 'ip', type: 'ip', indexed: true, analyzed: true, sortable: true, filterable: true },
{ name: 'request_body', type: 'attachment', indexed: true, analyzed: true, sortable: false, filterable: true },
{ name: 'point', type: 'geo_point', indexed: true, analyzed: true, sortable: false, filterable: false },
{ name: 'area', type: 'geo_shape', indexed: true, analyzed: true, sortable: true, filterable: false },
{ name: 'hashed', type: 'murmur3', indexed: true, analyzed: true, sortable: false, filterable: false },
{ name: 'geo.coordinates', type: 'geo_point', indexed: true, analyzed: true, sortable: false, filterable: true },
{ name: 'extension', type: 'string', indexed: true, analyzed: true, sortable: true, filterable: true },
{ name: 'machine.os', type: 'string', indexed: true, analyzed: true, sortable: true, filterable: true },
{ name: 'geo.src', type: 'string', indexed: true, analyzed: true, sortable: true, filterable: true },
{ name: '_type', type: 'string', indexed: false, analyzed: true, sortable: true, filterable: true },
{ name: '_id', type: 'string', indexed: false, analyzed: false, sortable: false, filterable: true},
{ name: '_source', type: 'string', indexed: false, analyzed: false, sortable: false, filterable: false},
{ name: 'custom_user_field', type: 'conflict', indexed: false, analyzed: false, sortable: false, filterable: true },
{ name: 'script string', type: 'string', scripted: true, script: '\'i am a string\'', lang: 'expression' },
{ name: 'script number', type: 'number', scripted: true, script: '1234', lang: 'expression' },
{ name: 'script date', type: 'date', scripted: true, script: '1234', lang: 'painless' },
{ name: 'script murmur3', type: 'murmur3', scripted: true, script: '1234', lang: 'expression'},
].map(function (field) {
field.count = field.count || 0;
field.scripted = field.scripted || false;
return field;
});
return [
// |indexed
// | |analyzed
// | | |aggregatable
// | | | |searchable
// name type | | | | |metadata
['bytes', 'number', true, true, true, true, { count: 10 } ],
['ssl', 'boolean', true, true, true, true, { count: 20 } ],
['@timestamp', 'date', true, true, true, true, { count: 30 } ],
['time', 'date', true, true, true, true, { count: 30 } ],
['@tags', 'string', true, true, true, true ],
['utc_time', 'date', true, true, true, true ],
['phpmemory', 'number', true, true, true, true ],
['ip', 'ip', true, true, true, true ],
['request_body', 'attachment', true, true, true, true ],
['point', 'geo_point', true, true, true, true ],
['area', 'geo_shape', true, true, true, true ],
['hashed', 'murmur3', true, true, false, true ],
['geo.coordinates', 'geo_point', true, true, true, true ],
['extension', 'string', true, true, true, true ],
['machine.os', 'string', true, true, true, true ],
['geo.src', 'string', true, true, true, true ],
['_id', 'string', false, false, true, true ],
['_type', 'string', false, false, true, true ],
['_source', 'string', false, false, true, true ],
['custom_user_field', 'conflict', false, false, true, true ],
['script string', 'string', false, false, true, false, { script: '\'i am a string\'' } ],
['script number', 'number', false, false, true, false, { script: '1234' } ],
['script date', 'date', false, false, true, false, { script: '1234', lang: 'painless' } ],
['script murmur3', 'murmur3', false, false, true, false, { script: '1234' } ],
].map(function (row) {
const [
name,
type,
indexed,
analyzed,
aggregatable,
searchable,
metadata = {}
] = row;

const {
count = 0,
script,
lang = script ? 'expression' : undefined,
scripted = !!script,
} = metadata;

return sourceData;
return {
name,
type,
indexed,
analyzed,
aggregatable,
searchable,
count,
script,
lang,
scripted,
};
});
}

export default stubbedLogstashFields;
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ describe('ResponseWriter class', function () {

it('collects the aggConfigs from each column in aggStack', function () {
let aggs = [
{ type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } },
{ type: 'date_histogram', schema: 'segment', params: { field: 'time' } },
{ type: 'terms', schema: 'segment', params: { field: 'extension' } },
{ type: 'avg', schema: 'metric', params: { field: '@timestamp' } }
{ type: 'avg', schema: 'metric', params: { field: 'bytes' } }
];

getColumns.returns(aggs.map(function (agg) {
Expand Down
3 changes: 1 addition & 2 deletions src/ui/public/agg_types/__tests__/agg_type.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ describe('AggType Class', function () {

describe('getFormat', function () {
it('returns the formatter for the aggConfig', function () {
let aggType = new AggType({});

let vis = new Vis(indexPattern, {
type: 'histogram',
aggs: [
Expand All @@ -94,6 +92,7 @@ describe('AggType Class', function () {
});

let aggConfig = vis.aggs.byTypeName.date_histogram[0];
const aggType = aggConfig.type;

expect(aggType.getFormat(aggConfig)).to.be(fieldFormat.getDefaultInstance('date'));

Expand Down
1 change: 1 addition & 0 deletions src/ui/public/agg_types/buckets/significant_terms.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default function SignificantTermsAggDefinition(Private) {
params: [
{
name: 'field',
scriptable: false,
filterFieldTypes: 'string'
},
{
Expand Down
1 change: 0 additions & 1 deletion src/ui/public/agg_types/buckets/terms.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export default function TermsAggDefinition(Private) {
params: [
{
name: 'field',
scriptable: true,
filterFieldTypes: ['number', 'boolean', 'date', 'ip', 'string']
},
{
Expand Down
45 changes: 40 additions & 5 deletions src/ui/public/agg_types/param_types/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ import { SavedObjectNotFound } from 'ui/errors';
import _ from 'lodash';
import editorHtml from 'ui/agg_types/controls/field.html';
import AggTypesParamTypesBaseProvider from 'ui/agg_types/param_types/base';
export default function FieldAggParamFactory(Private) {
import 'ui/filters/field_type';
import IndexedArray from 'ui/indexed_array';
import Notifier from 'ui/notify/notifier';

export default function FieldAggParamFactory(Private, $filter) {
let BaseAggParam = Private(AggTypesParamTypesBaseProvider);
const notifier = new Notifier();

_.class(FieldAggParam).inherits(BaseAggParam);
function FieldAggParam(config) {
FieldAggParam.Super.call(this, config);
}

FieldAggParam.prototype.editor = editorHtml;
FieldAggParam.prototype.scriptable = false;
FieldAggParam.prototype.scriptable = true;
FieldAggParam.prototype.filterFieldTypes = '*';

/**
Expand All @@ -25,6 +29,32 @@ export default function FieldAggParamFactory(Private) {
return field.name;
};

/**
* Get the options for this field from the indexPattern
*/
FieldAggParam.prototype.getFieldOptions = function (aggConfig) {
const indexPattern = aggConfig.getIndexPattern();
let fields = indexPattern.fields.raw;

fields = fields.filter(f => f.aggregatable);

if (!this.scriptable) {
fields = fields.filter(field => !field.scripted);
}

if (this.filterFieldTypes) {
fields = $filter('fieldType')(fields, this.filterFieldTypes);
}

fields = $filter('orderBy')(fields, ['type', 'name']);

return new IndexedArray({
index: ['name'],
group: ['type'],
initialSet: fields
});
};

/**
* Called to read values from a database record into the
* aggConfig object
Expand All @@ -33,13 +63,18 @@ export default function FieldAggParamFactory(Private) {
* @return {field}
*/
FieldAggParam.prototype.deserialize = function (fieldName, aggConfig) {
let field = aggConfig.vis.indexPattern.fields.byName[fieldName];
const field = aggConfig.getIndexPattern().fields.byName[fieldName];

if (!field) {
throw new SavedObjectNotFound('index-pattern-field', fieldName);
}

return field;
const validField = this.getFieldOptions(aggConfig).byName[fieldName];
if (!validField) {
notifier.error(`"field" is invalid`);
}

return validField;
};

/**
Expand All @@ -56,7 +91,7 @@ export default function FieldAggParamFactory(Private) {
let field = aggConfig.getField();

if (!field) {
throw new Error(`"${aggConfig.makeLabel()}" requires a field`);
throw new TypeError('"field" is a required parameter');
}

if (field.scripted) {
Expand Down
19 changes: 6 additions & 13 deletions src/ui/public/index_patterns/__tests__/_index_pattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import IndexPatternsMapperProvider from 'ui/index_patterns/_mapper';
import UtilsMappingSetupProvider from 'ui/utils/mapping_setup';
import IndexPatternsIntervalsProvider from 'ui/index_patterns/_intervals';
import IndexPatternsIndexPatternProvider from 'ui/index_patterns/_index_pattern';
import NoDigestPromises from 'test_utils/no_digest_promises';

describe('index pattern', function () {
NoDigestPromises.activateForSuite();

let IndexPattern;
let mapper;
let mappingSetup;
Expand Down Expand Up @@ -55,7 +58,7 @@ describe('index pattern', function () {

// stub calculateIndices
calculateIndices = sinon.spy(function () {
return $injector.get('Promise').resolve([
return Promise.resolve([
{ index: 'foo', max: Infinity, min: -Infinity },
{ index: 'bar', max: Infinity, min: -Infinity }
]);
Expand Down Expand Up @@ -150,7 +153,6 @@ describe('index pattern', function () {

describe('refresh fields', function () {
// override the default indexPattern, with a truncated field list
require('test_utils/no_digest_promises').activateForSuite();
const indexPatternId = 'test-pattern';
let indexPattern;
let fieldLength;
Expand Down Expand Up @@ -321,7 +323,6 @@ describe('index pattern', function () {
});

describe('#toDetailedIndexList', function () {
require('test_utils/no_digest_promises').activateForSuite();
context('when index pattern is an interval', function () {
let interval;
beforeEach(function () {
Expand Down Expand Up @@ -400,7 +401,6 @@ describe('index pattern', function () {

describe('#toIndexList', function () {
context('when index pattern is an interval', function () {
require('test_utils/no_digest_promises').activateForSuite();

let interval;
beforeEach(function () {
Expand Down Expand Up @@ -431,7 +431,6 @@ describe('index pattern', function () {
});

context('when index pattern is a time-base wildcard', function () {
require('test_utils/no_digest_promises').activateForSuite();
beforeEach(function () {
sinon.stub(indexPattern, 'getInterval').returns(false);
sinon.stub(indexPattern, 'hasTimeField').returns(true);
Expand All @@ -453,7 +452,6 @@ describe('index pattern', function () {
});

context('when index pattern is a time-base wildcard that is configured not to expand', function () {
require('test_utils/no_digest_promises').activateForSuite();
beforeEach(function () {
sinon.stub(indexPattern, 'getInterval').returns(false);
sinon.stub(indexPattern, 'hasTimeField').returns(true);
Expand All @@ -472,13 +470,8 @@ describe('index pattern', function () {
sinon.stub(indexPattern, 'getInterval').returns(false);
});

it('is fulfilled by id', function () {
let indexList;
indexPattern.toIndexList().then(function (val) {
indexList = val;
});
$rootScope.$apply();

it('is fulfilled by id', async function () {
let indexList = await indexPattern.toIndexList();
expect(indexList).to.equal(indexPattern.id);
});
});
Expand Down
8 changes: 5 additions & 3 deletions src/ui/public/notify/__tests__/notifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ describe('Notifier', function () {

beforeEach(function () {
params = { location: 'foo' };
while (Notifier.prototype._notifs.pop()); // clear global notifications
notifier = new Notifier(params);
});

afterEach(function () {
Notifier.prototype._notifs.length = 0; // clear global notifications
});

describe('#constructor()', function () {
it('sets #from from given location', function () {
expect(notifier.from).to.equal(params.location);
Expand Down Expand Up @@ -465,13 +468,12 @@ describe('Directive Notification', function () {
scope;
});

while (Notifier.prototype._notifs.pop()); // clear global notifications

notifier = new Notifier({ location: 'directiveFoo' });
directiveNotification = notifier.directive(directiveParam, customParams);
});

afterEach(() => {
Notifier.prototype._notifs.length = 0; // clear global notifications
directiveNotification.clear();
scope.$destroy();
});
Expand Down
Loading