mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Do not match exclusion on meta/scripted fields. Disable filter bar when on 'Filter fields' tab. Removed exclusion checkbox in the field controls page. Corrected typos. Improved documentation phrasing.
This commit is contained in:
parent
4be31b2878
commit
79e87ca3ae
12 changed files with 63 additions and 83 deletions
|
@ -32,7 +32,7 @@
|
|||
</div>
|
||||
|
||||
<form role="form">
|
||||
<input aria-label="Filter" ng-model="fieldFilter" class="form-control span12" type="text" placeholder="Filter" />
|
||||
<input ng-disabled="state.tab == 'fieldFilters'" aria-label="Filter" ng-model="fieldFilter" class="form-control span12" type="text" placeholder="Filter" />
|
||||
</form>
|
||||
|
||||
<br />
|
||||
|
|
|
@ -5,13 +5,14 @@ import typeHtml from 'plugins/kibana/settings/sections/indices/_field_type.html'
|
|||
import controlsHtml from 'plugins/kibana/settings/sections/indices/_field_controls.html';
|
||||
import uiModules from 'ui/modules';
|
||||
import indexedFieldsTemplate from 'plugins/kibana/settings/sections/indices/_indexed_fields.html';
|
||||
import { fieldWildcardMatcher } from 'ui/field_wildcard';
|
||||
import FieldWildcardProvider from 'ui/field_wildcard';
|
||||
|
||||
uiModules.get('apps/settings')
|
||||
.directive('settingsIndicesIndexedFields', function ($filter) {
|
||||
.directive('settingsIndicesIndexedFields', function (Private, $filter) {
|
||||
const yesTemplate = '<i class="fa fa-check" aria-label="yes"></i>';
|
||||
const noTemplate = '';
|
||||
const filter = $filter('filter');
|
||||
const { fieldWildcardMatcher } = Private(FieldWildcardProvider);
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
|
@ -42,7 +43,7 @@ uiModules.get('apps/settings')
|
|||
const childScope = _.assign($scope.$new(), { field: field });
|
||||
rowScopes.push(childScope);
|
||||
|
||||
const excluded = field.exclude || fieldWildcardMatch(field.name);
|
||||
const excluded = fieldWildcardMatch(field.name);
|
||||
|
||||
return [
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<h3>Field Filters</h3>
|
||||
|
||||
<p>
|
||||
Field filters can be used to exclude one or more fields when fetching the document source. This happens in apps like Discover for the doc table. Each row is built using the source of a single document, and if you have documents with large or unimportant fields you may benefit from filtering those out at this lowere level.
|
||||
Field filters can be used to exclude one or more fields when fetching the document source. This happens when viewing a document in the Discover app, or with a table displaying results from a saved search in the Dashboard app. Each row is built using the source of a single document, and if you have documents with large or unimportant fields you may benefit from filtering those out at this lower level.
|
||||
</p>
|
||||
|
||||
<div ng-class="{ saving: fieldFilters.saving }" class="field-filters-container">
|
||||
|
@ -22,7 +22,7 @@
|
|||
ng-model="filter.value"
|
||||
input-focus
|
||||
ng-if="fieldFilters.editting === filter"
|
||||
placeholder="field name filter, accepts wildcards (i.e. `user:*`)"
|
||||
placeholder="field name filter, accepts wildcards (e.g., `user*` to filter fields starting with 'user')"
|
||||
type="text"
|
||||
required
|
||||
class="form-control">
|
||||
|
@ -63,7 +63,7 @@
|
|||
<div class="input-group">
|
||||
<input
|
||||
ng-model="fieldFilters.newValue"
|
||||
placeholder="field name filter, accepts wildcards (i.e. `user:*`)"
|
||||
placeholder="field name filter, accepts wildcards (e.g., `user*` to filter fields starting with 'user')"
|
||||
type="text"
|
||||
class="form-control">
|
||||
|
||||
|
@ -88,7 +88,7 @@
|
|||
<em>The selected field filters don't match any known fields.</em>
|
||||
</p>
|
||||
<p ng-if="fieldFilters.sampleMatches">
|
||||
Based on the choosen field filters, these are the known fields that would be excluded from document sources.
|
||||
Based on the chosen field filters, these are the known fields that would be excluded from document sources.
|
||||
</p>
|
||||
<ul>
|
||||
<li ng-repeat="match in fieldFilters.sampleMatches">{{match}}</li>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { size, without } from 'lodash';
|
|||
|
||||
import uiModules from 'ui/modules';
|
||||
import Notifier from 'ui/notify/notifier';
|
||||
import { fieldWildcardMatcher } from 'ui/field_wildcard';
|
||||
import FieldWildcardProvider from 'ui/field_wildcard';
|
||||
|
||||
import template from './field_filters.html';
|
||||
import './field_filters.less';
|
||||
|
@ -10,7 +10,8 @@ import './field_filters.less';
|
|||
const notify = new Notifier();
|
||||
|
||||
uiModules.get('kibana')
|
||||
.directive('settingsIndicesFieldFilters', function () {
|
||||
.directive('settingsIndicesFieldFilters', function (Private) {
|
||||
const { fieldWildcardMatcher } = Private(FieldWildcardProvider);
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
|
@ -32,7 +33,7 @@ uiModules.get('kibana')
|
|||
$scope.$watch('indexPattern.fieldFilters', (filters) => {
|
||||
const values = filters.map(f => f.value);
|
||||
const filter = fieldWildcardMatcher(values);
|
||||
const matches = $scope.indexPattern.fields.map(f => f.name).filter(filter).sort();
|
||||
const matches = $scope.indexPattern.getNonScriptedFields().map(f => f.name).filter(filter).sort();
|
||||
this.sampleMatches = size(matches) ? matches : null;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ module.exports = function initDefaultFieldProps(fields) {
|
|||
analyzed: true,
|
||||
doc_values: false,
|
||||
scripted: false,
|
||||
exclude: false,
|
||||
count: 0
|
||||
});
|
||||
|
||||
|
@ -28,7 +27,6 @@ module.exports = function initDefaultFieldProps(fields) {
|
|||
analyzed: false,
|
||||
doc_values: true,
|
||||
scripted: false,
|
||||
exclude: false,
|
||||
count: 0
|
||||
});
|
||||
}
|
||||
|
@ -38,7 +36,6 @@ module.exports = function initDefaultFieldProps(fields) {
|
|||
analyzed: false,
|
||||
doc_values: true,
|
||||
scripted: false,
|
||||
exclude: false,
|
||||
count: 0
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,12 +7,13 @@ import RequestQueueProvider from '../_request_queue';
|
|||
import ErrorHandlersProvider from '../_error_handlers';
|
||||
import FetchProvider from '../fetch';
|
||||
import DecorateQueryProvider from './_decorate_query';
|
||||
import { fieldWildcardFilter } from '../../field_wildcard';
|
||||
import FieldWildcardProvider from '../../field_wildcard';
|
||||
|
||||
export default function SourceAbstractFactory(Private, Promise, PromiseEmitter) {
|
||||
let requestQueue = Private(RequestQueueProvider);
|
||||
let errorHandlers = Private(ErrorHandlersProvider);
|
||||
let courierFetch = Private(FetchProvider);
|
||||
let { fieldWildcardFilter } = Private(FieldWildcardProvider);
|
||||
|
||||
function SourceAbstract(initialState, strategy) {
|
||||
let self = this;
|
||||
|
|
|
@ -83,38 +83,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<span class="pull-right text-info hintbox-label" ng-click="editor.showExcludeHelp = !editor.showExcludeHelp">
|
||||
<i class="fa fa-info"></i> Help
|
||||
</span>
|
||||
|
||||
<label><input ng-disabled="isMetaField" type="checkbox" ng-model="editor.field.exclude"> Exclude from _source</label>
|
||||
|
||||
<div class="hintbox" ng-if="isMetaField">
|
||||
<h4 class="hintbox-heading">
|
||||
<i class="fa fa-warning text-warning"></i> Field Exclusion
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
You cannot exclude metadata fields.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="hintbox" ng-if="editor.showExcludeHelp">
|
||||
<h4 class="hintbox-heading">
|
||||
<i class="fa fa-info text-info"></i> Field Exclusion
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
If checked, this field will be filtered from the <b>_source</b> of each document using
|
||||
<a target="_window" href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html">source filtering<i aria-hidden="true" class="fa-link fa"></i></a>. This only impacts views that fetch the _source for documents, like Discover or the doc table.
|
||||
</p>
|
||||
<p>
|
||||
If this field is explicitly selected in your saved search, then it will not be excluded.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="editor.field.scripted">
|
||||
<div class="form-group">
|
||||
<label>Script</label>
|
||||
|
|
|
@ -36,7 +36,6 @@ uiModules
|
|||
self.indexPattern = $scope.getIndexPattern();
|
||||
self.field = shadowCopy($scope.getField());
|
||||
self.formatParams = self.field.format.params();
|
||||
$scope.isMetaField = _.contains(metaFields, self.field.name);
|
||||
|
||||
// only init on first create
|
||||
self.creating = !self.indexPattern.fields.byName[self.field.name];
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
import expect from 'expect.js';
|
||||
import ngMock from 'ng_mock';
|
||||
|
||||
import { makeRegEx, fieldWildcardFilter } from '../field_wildcard';
|
||||
import FieldWildcardProvider from '../../field_wildcard';
|
||||
|
||||
describe('fieldWildcard', function () {
|
||||
let fieldWildcardFilter;
|
||||
let makeRegEx;
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject(function (config, Private) {
|
||||
config.set('metaFields', ['_id', '_type', '_source']);
|
||||
const fieldWildcard = Private(FieldWildcardProvider);
|
||||
fieldWildcardFilter = fieldWildcard.fieldWildcardFilter;
|
||||
makeRegEx = fieldWildcard.makeRegEx;
|
||||
}));
|
||||
|
||||
describe('makeRegEx', function () {
|
||||
it('matches * in any position', function () {
|
||||
expect('aaaaaabbbbbbbcccccc').to.match(makeRegEx('*a*b*c*'));
|
||||
|
@ -38,6 +50,18 @@ describe('fieldWildcard', function () {
|
|||
expect(original.filter(filter)).to.eql(original);
|
||||
});
|
||||
|
||||
it('does not filter metaFields', function () {
|
||||
const filter = fieldWildcardFilter([ '_*' ]);
|
||||
|
||||
const original = [
|
||||
'_id',
|
||||
'_type',
|
||||
'_typefake'
|
||||
];
|
||||
|
||||
expect(original.filter(filter)).to.eql(['_id', '_type']);
|
||||
});
|
||||
|
||||
it('filters values that match the globs', function () {
|
||||
const filter = fieldWildcardFilter([
|
||||
'f*',
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
import { escapeRegExp, memoize } from 'lodash';
|
||||
|
||||
export const makeRegEx = memoize(function makeRegEx(glob) {
|
||||
return new RegExp('^' + glob.split('*').map(escapeRegExp).join('.*') + '$');
|
||||
});
|
||||
export default function fieldWildcard(config) {
|
||||
const metaFields = config.get('metaFields');
|
||||
|
||||
export function fieldWildcardMatcher(globs) {
|
||||
return function matcher(val) {
|
||||
return globs.some(p => makeRegEx(p).test(val));
|
||||
};
|
||||
}
|
||||
const makeRegEx = memoize(function makeRegEx(glob) {
|
||||
return new RegExp('^' + glob.split('*').map(escapeRegExp).join('.*') + '$');
|
||||
});
|
||||
|
||||
export function fieldWildcardFilter(globs) {
|
||||
const matcher = fieldWildcardMatcher(globs);
|
||||
return function filter(val) {
|
||||
return !matcher(val);
|
||||
};
|
||||
}
|
||||
function fieldWildcardMatcher(globs) {
|
||||
return function matcher(val) {
|
||||
return metaFields.indexOf(val) === -1 && globs.some(p => makeRegEx(p).test(val));
|
||||
};
|
||||
}
|
||||
|
||||
function fieldWildcardFilter(globs) {
|
||||
const matcher = fieldWildcardMatcher(globs, config);
|
||||
return function filter(val) {
|
||||
return !matcher(val);
|
||||
};
|
||||
}
|
||||
|
||||
return { makeRegEx, fieldWildcardMatcher, fieldWildcardFilter };
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import ObjDefine from 'ui/utils/obj_define';
|
|||
import IndexPatternsFieldFormatFieldFormatProvider from 'ui/index_patterns/_field_format/field_format';
|
||||
import IndexPatternsFieldTypesProvider from 'ui/index_patterns/_field_types';
|
||||
import RegistryFieldFormatsProvider from 'ui/registry/field_formats';
|
||||
export default function FieldObjectProvider(Private, shortDotsFilter, $rootScope, Notifier, config) {
|
||||
export default function FieldObjectProvider(Private, shortDotsFilter, $rootScope, Notifier) {
|
||||
let notify = new Notifier({ location: 'IndexPattern Field' });
|
||||
let FieldFormat = Private(IndexPatternsFieldFormatFieldFormatProvider);
|
||||
let fieldTypes = Private(IndexPatternsFieldTypesProvider);
|
||||
|
@ -42,12 +42,10 @@ export default function FieldObjectProvider(Private, shortDotsFilter, $rootScope
|
|||
let scripted = !!spec.scripted;
|
||||
let sortable = spec.name === '_score' || ((indexed || scripted) && type.sortable);
|
||||
let filterable = spec.name === '_id' || scripted || (indexed && type.filterable);
|
||||
let isMetaField = config.get('metaFields').includes(spec.name);
|
||||
|
||||
obj.fact('name');
|
||||
obj.fact('type');
|
||||
obj.writ('count', spec.count || 0);
|
||||
obj.fact('exclude', Boolean(!isMetaField && spec.exclude));
|
||||
|
||||
// scripted objs
|
||||
obj.fact('scripted', scripted);
|
||||
|
|
|
@ -138,14 +138,9 @@ export default function IndexPatternFactory(Private, timefilter, Notifier, confi
|
|||
};
|
||||
|
||||
// Get the source filtering configuration for that index.
|
||||
// Fields which name appears in the given columns array will not be excluded.
|
||||
self.getSourceFiltering = function (columns) {
|
||||
self.getSourceFiltering = function () {
|
||||
return {
|
||||
exclude: self
|
||||
.getNonScriptedFields()
|
||||
.filter(field => field.exclude && !_.contains(columns, field.name))
|
||||
.map(field => field.name)
|
||||
.concat(self.fieldFilters.map(filter => filter.value))
|
||||
exclude: self.fieldFilters.map(filter => filter.value)
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -309,18 +304,8 @@ export default function IndexPatternFactory(Private, timefilter, Notifier, confi
|
|||
};
|
||||
|
||||
self._fetchFields = function () {
|
||||
const existingFieldsByName = _.get(self, 'fields.byName', {});
|
||||
|
||||
return mapper.getFieldsForIndexPattern(self, true)
|
||||
.then(function (fields) {
|
||||
// copy over kibana-added properties from existing fields
|
||||
fields.forEach(function (field) {
|
||||
var existingField = existingFieldsByName[field.name];
|
||||
if (existingField) {
|
||||
field.exclude = existingField.exclude;
|
||||
}
|
||||
});
|
||||
|
||||
// append existing scripted fields
|
||||
fields = fields.concat(self.getScriptedFields());
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue