mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
ditched the new 'retrieved fields' tab and added checkbox to exclude a field in the field control
This commit is contained in:
parent
e7204bef63
commit
b228c66c01
12 changed files with 44 additions and 279 deletions
|
@ -1,60 +0,0 @@
|
|||
var expect = require('expect.js');
|
||||
|
||||
define(function (require) {
|
||||
var isRetrieved = require('src/plugins/kibana/public/settings/sections/indices/retrieved_field');
|
||||
|
||||
describe('Settings', function () {
|
||||
describe('Indices', function () {
|
||||
describe('isRetrieved(sourceFiltering, name)', function () {
|
||||
it('should be a function', function () {
|
||||
expect(isRetrieved).to.be.a(Function);
|
||||
});
|
||||
|
||||
it('should retrieve john', function () {
|
||||
var sourceFiltering = {
|
||||
include: 'john'
|
||||
};
|
||||
|
||||
expect(isRetrieved(sourceFiltering, 'john')).to.be(true);
|
||||
});
|
||||
|
||||
it('should not retrieve connor', function () {
|
||||
var sourceFiltering = {
|
||||
exclude: 'connor'
|
||||
};
|
||||
|
||||
expect(isRetrieved(sourceFiltering, 'connor')).to.be(false);
|
||||
});
|
||||
|
||||
it('should retrieve connor', function () {
|
||||
var sourceFiltering = {
|
||||
exclude: '*.connor'
|
||||
};
|
||||
|
||||
expect(isRetrieved(sourceFiltering, 'connor')).to.be(true);
|
||||
expect(isRetrieved(sourceFiltering, 'john.connor')).to.be(false);
|
||||
});
|
||||
|
||||
it('should not retrieve neither john nor connor', function () {
|
||||
var sourceFiltering = {
|
||||
exclude: [ 'john', 'connor' ]
|
||||
};
|
||||
|
||||
expect(isRetrieved(sourceFiltering, 'connor')).to.be(false);
|
||||
expect(isRetrieved(sourceFiltering, 'john')).to.be(false);
|
||||
expect(isRetrieved(sourceFiltering, 'toto')).to.be(true);
|
||||
});
|
||||
|
||||
it('should not retrieve john.*.connor', function () {
|
||||
var sourceFiltering = {
|
||||
exclude: 'john.*.connor'
|
||||
};
|
||||
|
||||
expect(isRetrieved(sourceFiltering, 'john.j.connor')).to.be(false);
|
||||
expect(isRetrieved(sourceFiltering, 'john.t.connor')).to.be(false);
|
||||
expect(isRetrieved(sourceFiltering, 'john.j.watterson')).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -41,14 +41,13 @@
|
|||
<li class="kbn-settings-tab" ng-class="{ active: state.tab === fieldType.index }" ng-repeat="fieldType in fieldTypes">
|
||||
<a ng-click="changeTab(fieldType)">
|
||||
{{ fieldType.title }}
|
||||
<small ng-if="fieldType.count !== undefined">({{ fieldType.count }})</small>
|
||||
<small>({{ fieldType.count }})</small>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<indexed-fields ng-show="state.tab == 'indexedFields'" class="fields indexed-fields"></indexed-fields>
|
||||
<scripted-fields ng-show="state.tab == 'scriptedFields'" class="fields scripted-fields"></scripted-fields>
|
||||
<source-filtering ng-show="state.tab == 'sourceFiltering'" class="fields source-filtering"></source-filtering>
|
||||
|
||||
</div>
|
||||
</kbn-settings-indices>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import _ from 'lodash';
|
||||
import isRetrieved from 'plugins/kibana/settings/sections/indices/retrieved_field';
|
||||
import 'ui/paginated_table';
|
||||
import nameHtml from 'plugins/kibana/settings/sections/indices/_field_name.html';
|
||||
import typeHtml from 'plugins/kibana/settings/sections/indices/_field_type.html';
|
||||
|
@ -44,7 +43,6 @@ uiModules.get('apps/settings')
|
|||
const childScope = _.assign($scope.$new(), { field: field });
|
||||
rowScopes.push(childScope);
|
||||
|
||||
<<<<<<< HEAD
|
||||
return [
|
||||
{
|
||||
markup: nameHtml,
|
||||
|
@ -66,7 +64,8 @@ uiModules.get('apps/settings')
|
|||
value: field.indexed
|
||||
},
|
||||
{
|
||||
markup: isRetrieved(sourceFiltering, field.displayName) ? yesTemplate : noTemplate
|
||||
markup: field.exclude ? noTemplate : yesTemplate,
|
||||
value: field.exclude
|
||||
},
|
||||
{
|
||||
markup: controlsHtml,
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
<h3>Retrieved fields
|
||||
|
||||
<span class="pull-right text-info hintbox-label" ng-click="showHelp = !showHelp">
|
||||
<h4><i class="fa fa-info"></i> Retrieved Fields Help</h4>
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
<div class="hintbox" ng-if="showHelp">
|
||||
<h4 class="hintbox-heading">
|
||||
<i class="fa fa-question-circle text-info"></i> Retrieved Fields Help
|
||||
</h4>
|
||||
|
||||
<p>
|
||||
All fields are by default retrieved and are available inside the "_source" object of each hit. Thanks to the
|
||||
<a target="_window" href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html">
|
||||
source filtering API
|
||||
<i aria-hidden="true" class="fa-link fa"></i>
|
||||
</a>
|
||||
of Elasticsearch, you can choose which fields are actually retrieved. The value needs to be a JSON object.
|
||||
</p>
|
||||
|
||||
<br/>
|
||||
<strong>Examples</strong>
|
||||
|
||||
<p style="color: #b4bcc2;">Exclusion of a single field</p>
|
||||
|
||||
<div
|
||||
readonly
|
||||
ui-ace="{
|
||||
advanced: {
|
||||
highlightActiveLine: false
|
||||
},
|
||||
useWrapMode: true,
|
||||
rendererOptions: {
|
||||
showPrintMargin: false,
|
||||
maxLines: 4294967296
|
||||
},
|
||||
mode: 'json'
|
||||
}">{
|
||||
"exclude": "user"
|
||||
}</div>
|
||||
|
||||
<p style="color: #b4bcc2;">Exclusion with a path pattern</p>
|
||||
<div
|
||||
readonly
|
||||
ui-ace="{
|
||||
advanced: {
|
||||
highlightActiveLine: false
|
||||
},
|
||||
useWrapMode: true,
|
||||
rendererOptions: {
|
||||
showPrintMargin: false,
|
||||
maxLines: 4294967296
|
||||
},
|
||||
mode: 'json'
|
||||
}">{
|
||||
"exclude": [
|
||||
"obj1.*",
|
||||
"*.value"
|
||||
]
|
||||
}</div>
|
||||
|
||||
<p style="color: #b4bcc2;">Complete control with exclusions and inclusion</p>
|
||||
<div
|
||||
readonly
|
||||
ui-ace="{
|
||||
advanced: {
|
||||
highlightActiveLine: false
|
||||
},
|
||||
useWrapMode: true,
|
||||
rendererOptions: {
|
||||
showPrintMargin: false,
|
||||
maxLines: 4294967296
|
||||
},
|
||||
mode: 'json'
|
||||
}">{
|
||||
"exclude": "obj1.*",
|
||||
"include": "obj2.*.val"
|
||||
}</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
By default, all fields are retrieved to populate results table.
|
||||
Sometimes however some fields can be very large and seriously affect performance. This can be often the case when you have materialized one to many relationships, e.g., an entity having many nested entities. Those fields are still useful for searching or analytics but not in a result table.<br/><br/>
|
||||
Use this setting to decide what to include or exclude in the data retrieved from the Elasticsearch index.<br/>
|
||||
If empty, all fields are retrieved.
|
||||
</p>
|
||||
|
||||
<form ng-submit="save()" name="form">
|
||||
<div
|
||||
id="json-ace"
|
||||
ng-model="sourceFiltering"
|
||||
ui-ace="{
|
||||
useWrapMode: true,
|
||||
advanced: {
|
||||
highlightActiveLine: false
|
||||
},
|
||||
rendererOptions: {
|
||||
showPrintMargin: false,
|
||||
maxLines: 4294967296
|
||||
},
|
||||
mode: 'json'
|
||||
}">{{ sourceFiltering | json }}</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button
|
||||
ng-disabled="form.$invalid"
|
||||
type="submit"
|
||||
aria-label="Submit"
|
||||
class="btn btn-success">
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
|
@ -1,44 +0,0 @@
|
|||
define(function (require) {
|
||||
require('ui/modules').get('apps/settings')
|
||||
.directive('sourceFiltering', function (Notifier, $window) {
|
||||
var notify = new Notifier();
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: require('plugins/kibana/settings/sections/indices/_source_filtering.html'),
|
||||
link: function ($scope) {
|
||||
$scope.showHelp = false;
|
||||
$scope.sourceFiltering = JSON.stringify($scope.indexPattern.getSourceFiltering(), null, ' ');
|
||||
$scope.save = function () {
|
||||
try {
|
||||
var sourceFiltering;
|
||||
|
||||
if ($scope.sourceFiltering) {
|
||||
sourceFiltering = JSON.parse($scope.sourceFiltering);
|
||||
if (sourceFiltering.constructor !== Object) {
|
||||
throw 'You must enter a JSON object with exclude/include field(s)';
|
||||
}
|
||||
for (var att in sourceFiltering) {
|
||||
if (sourceFiltering.hasOwnProperty(att) && att !== 'exclude' && att !== 'include') {
|
||||
throw 'The JSON object should have only either an exclude or an include field';
|
||||
}
|
||||
}
|
||||
$scope.indexPattern.setSourceFiltering(sourceFiltering);
|
||||
notify.info('Updated the set of retrieved fields');
|
||||
} else if ($scope.indexPattern.getSourceFiltering()) {
|
||||
var confirmIfEmpty = 'The following configuration will be deleted:\n\n' +
|
||||
JSON.stringify($scope.indexPattern.getSourceFiltering(), null, ' ');
|
||||
if ($window.confirm(confirmIfEmpty)) {
|
||||
$scope.indexPattern.setSourceFiltering(undefined);
|
||||
notify.info('All fields are now retrieved');
|
||||
} else {
|
||||
$scope.sourceFiltering = JSON.stringify($scope.indexPattern.getSourceFiltering(), null, ' ');
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
notify.error(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -1,50 +0,0 @@
|
|||
define(function (require) {
|
||||
/**
|
||||
* Returns true if the path matches the given pattern
|
||||
*/
|
||||
function matchPath(pathPattern, path) {
|
||||
var pattern = pathPattern.split('.');
|
||||
var pathArr = path.split('.');
|
||||
|
||||
if (pattern.length !== pathArr.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < pattern.length; i++) {
|
||||
if (pattern[i] !== '*' && pattern[i] !== pathArr[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function process(val, name) {
|
||||
if (val.constructor === Array) {
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
if (matchPath(val[i], name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return matchPath(val, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the field named "name" should be retrieved as part of
|
||||
* the _source object for each hit.
|
||||
*/
|
||||
return function isRetrieved(sourceFiltering, name) {
|
||||
if (sourceFiltering === undefined) {
|
||||
return true;
|
||||
}
|
||||
if (sourceFiltering.include) {
|
||||
var inc = sourceFiltering.include;
|
||||
return process(inc, name);
|
||||
} else if (sourceFiltering.exclude) {
|
||||
var exc = sourceFiltering.exclude;
|
||||
return !process(exc, name);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
});
|
|
@ -17,6 +17,7 @@ module.exports = function initDefaultFieldProps(fields) {
|
|||
analyzed: true,
|
||||
doc_values: false,
|
||||
scripted: false,
|
||||
exclude: false,
|
||||
count: 0
|
||||
});
|
||||
|
||||
|
@ -27,6 +28,7 @@ module.exports = function initDefaultFieldProps(fields) {
|
|||
analyzed: false,
|
||||
doc_values: true,
|
||||
scripted: false,
|
||||
exclude: false,
|
||||
count: 0
|
||||
});
|
||||
}
|
||||
|
@ -36,6 +38,7 @@ module.exports = function initDefaultFieldProps(fields) {
|
|||
analyzed: false,
|
||||
doc_values: true,
|
||||
scripted: false,
|
||||
exclude: false,
|
||||
count: 0
|
||||
});
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ uiModules.get('kibana')
|
|||
|
||||
$scope.searchSource.size(config.get('discover:sampleSize'));
|
||||
$scope.searchSource.sort(getSort($scope.sorting, $scope.indexPattern));
|
||||
const sourceFiltering = $scope.indexPattern.getSourceFiltering();
|
||||
const sourceFiltering = $scope.indexPattern.getSourceFiltering($scope.columns);
|
||||
if (sourceFiltering) {
|
||||
$scope.searchSource.source(sourceFiltering);
|
||||
}
|
||||
|
|
|
@ -83,6 +83,32 @@
|
|||
</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 type="checkbox" ng-model="editor.field.exclude"> Exclude from _source</label>
|
||||
|
||||
<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 not be retrieved as part of the <b>_source</b> object. This is thanks to the
|
||||
<a target="_window" href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html">
|
||||
source filtering API
|
||||
<i aria-hidden="true" class="fa-link fa"></i>
|
||||
</a>
|
||||
of Elasticsearch.
|
||||
</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>
|
||||
|
|
|
@ -46,6 +46,7 @@ export default function FieldObjectProvider(Private, shortDotsFilter, $rootScope
|
|||
obj.fact('name');
|
||||
obj.fact('type');
|
||||
obj.writ('count', spec.count || 0);
|
||||
obj.writ('exclude', spec.exclude);
|
||||
|
||||
// scripted objs
|
||||
obj.fact('scripted', scripted);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<<<<<<< HEAD
|
||||
import _ from 'lodash';
|
||||
import errors from 'ui/errors';
|
||||
import angular from 'angular';
|
||||
|
@ -36,7 +35,6 @@ export default function IndexPatternFactory(Private, timefilter, Notifier, confi
|
|||
timeFieldName: 'string',
|
||||
notExpandable: 'boolean',
|
||||
intervalName: 'string',
|
||||
sourceFiltering: 'json',
|
||||
fields: 'json',
|
||||
fieldFormatMap: {
|
||||
type: 'string',
|
||||
|
@ -127,9 +125,15 @@ export default function IndexPatternFactory(Private, timefilter, Notifier, confi
|
|||
self.save();
|
||||
};
|
||||
|
||||
// Get the source filtering configuration for that index
|
||||
self.getSourceFiltering = function () {
|
||||
return self.sourceFiltering;
|
||||
// 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) {
|
||||
return {
|
||||
exclude: _(self.getNonScriptedFields())
|
||||
.filter((field) => field.exclude && !_.contains(columns, field.name))
|
||||
.map((field) => field.name)
|
||||
.value()
|
||||
};
|
||||
};
|
||||
|
||||
function initFields(fields) {
|
||||
|
|
|
@ -51,6 +51,7 @@ import {
|
|||
'format',
|
||||
'analyzed',
|
||||
'indexed',
|
||||
'retrieved',
|
||||
'controls'
|
||||
];
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue