mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Merge pull request #3571 from w33ble/sort-by-scripted
Allow sorting by scripted fields
This commit is contained in:
commit
4c3d06fdf0
8 changed files with 134 additions and 57 deletions
|
@ -1,29 +1,53 @@
|
|||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
return function normalizeSortRequest(config) {
|
||||
var defaultSortOptions = config.get('sort:options');
|
||||
|
||||
/**
|
||||
* Decorate queries with default parameters
|
||||
* @param {query} query object
|
||||
* @returns {object}
|
||||
*/
|
||||
return function (sortObject) {
|
||||
if (!_.isArray(sortObject)) sortObject = [sortObject];
|
||||
var defaultSortOptions = config.get('sort:options');
|
||||
return function (sortObject, indexPattern) {
|
||||
var normalizedSort = [];
|
||||
|
||||
/*
|
||||
Normalize the sort description to the more verbose format:
|
||||
{ someField: "desc" } into { someField: { "order": "desc"}}
|
||||
*/
|
||||
_.each(sortObject, function (sortable) {
|
||||
var sortField = _.keys(sortable)[0];
|
||||
var sortValue = sortable[sortField];
|
||||
if (_.isString(sortValue)) {
|
||||
sortValue = sortable[sortField] = { order: sortValue };
|
||||
}
|
||||
_.defaults(sortValue, defaultSortOptions);
|
||||
// [].concat({}) -> [{}], [].concat([{}]) -> [{}]
|
||||
return [].concat(sortObject).map(function (sortable) {
|
||||
return normalize(sortable, indexPattern);
|
||||
});
|
||||
return sortObject;
|
||||
};
|
||||
|
||||
/*
|
||||
Normalize the sort description to the more verbose format:
|
||||
{ someField: "desc" } into { someField: { "order": "desc"}}
|
||||
*/
|
||||
function normalize(sortable, indexPattern) {
|
||||
var normalized = {};
|
||||
var sortField = _.keys(sortable)[0];
|
||||
var sortValue = sortable[sortField];
|
||||
var indexField = indexPattern.fields.byName[sortField];
|
||||
|
||||
if (indexField && indexField.scripted && indexField.sortable) {
|
||||
var direction;
|
||||
if (_.isString(sortValue)) direction = sortValue;
|
||||
if (_.isObject(sortValue) && sortValue.order) direction = sortValue.order;
|
||||
|
||||
sortField = '_script';
|
||||
sortValue = {
|
||||
script: indexField.script,
|
||||
type: indexField.type,
|
||||
order: direction
|
||||
};
|
||||
} else {
|
||||
if (_.isString(sortValue)) {
|
||||
sortValue = { order: sortValue };
|
||||
}
|
||||
sortValue = _.defaults({}, sortValue, defaultSortOptions);
|
||||
}
|
||||
|
||||
normalized[sortField] = sortValue;
|
||||
return normalized;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ define(function (require) {
|
|||
var SegmentedRequest = Private(require('components/courier/fetch/request/segmented'));
|
||||
var normalizeSortRequest = Private(require('components/courier/data_source/_normalize_sort_request'));
|
||||
|
||||
|
||||
_(SearchSource).inherits(SourceAbstract);
|
||||
function SearchSource(initialState) {
|
||||
SearchSource.Super.call(this, initialState);
|
||||
|
@ -179,7 +178,7 @@ define(function (require) {
|
|||
key = '_source';
|
||||
/* fall through */
|
||||
case 'sort':
|
||||
val = normalizeSortRequest(val);
|
||||
val = normalizeSortRequest(val, this.get('index'));
|
||||
/* fall through */
|
||||
default:
|
||||
state.body = state.body || {};
|
||||
|
|
|
@ -23,7 +23,8 @@ define(function (require) {
|
|||
};
|
||||
|
||||
$scope.tooltip = function (column) {
|
||||
if (!sortableField(column)) return ''; else return 'Sort by ' + shortDotsFilter(column);
|
||||
if (!sortableField(column)) return '';
|
||||
return 'Sort by ' + shortDotsFilter(column);
|
||||
};
|
||||
|
||||
$scope.canRemove = function (name) {
|
||||
|
|
|
@ -40,4 +40,4 @@ define(function (require) {
|
|||
};
|
||||
|
||||
return getSort;
|
||||
});
|
||||
});
|
|
@ -38,7 +38,8 @@ define(function (require) {
|
|||
|
||||
var indexed = !!spec.indexed;
|
||||
var scripted = !!spec.scripted;
|
||||
var sortable = indexed && type.sortable;
|
||||
|
||||
var sortable = (indexed || scripted) && type.sortable;
|
||||
var bucketable = indexed || scripted;
|
||||
var filterable = spec.name === '_id' || scripted || (indexed && type.filterable);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ define(function (require) {
|
|||
{ 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 murmur3', type: 'murmur3', scripted: true, script: '1234', lang: 'expression'},
|
||||
].map(function (field) {
|
||||
field.count = field.count || 0;
|
||||
field.scripted = field.scripted || false;
|
||||
|
|
|
@ -4,45 +4,86 @@ define(function (require) {
|
|||
require('angular').module('normalizeSortRequest', ['kibana']);
|
||||
|
||||
var normalizeSortRequest;
|
||||
var indexPattern;
|
||||
var normalizedSort;
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
beforeEach(inject(function (Private) {
|
||||
normalizeSortRequest = Private(require('components/courier/data_source/_normalize_sort_request'));
|
||||
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
|
||||
|
||||
normalizedSort = [{
|
||||
someField: {
|
||||
order: 'desc',
|
||||
unmapped_type: 'boolean'
|
||||
}
|
||||
}];
|
||||
}));
|
||||
|
||||
var normalizedSort = [{
|
||||
someField: {
|
||||
order: 'desc',
|
||||
unmapped_type: 'boolean'
|
||||
}
|
||||
}];
|
||||
|
||||
it('make sure sort is an array', function () {
|
||||
var result = normalizeSortRequest(
|
||||
{ someField: 'desc'}
|
||||
);
|
||||
it('should return an array', function () {
|
||||
var sortable = { someField: 'desc'};
|
||||
var result = normalizeSortRequest(sortable, indexPattern);
|
||||
expect(result).to.be.an(Array);
|
||||
expect(result).to.eql(normalizedSort);
|
||||
// ensure object passed in is not mutated
|
||||
expect(result[0]).to.not.be.equal(sortable);
|
||||
expect(sortable).to.eql({ someField: 'desc'});
|
||||
});
|
||||
|
||||
it('makes plain string sort into the more verbose format', function () {
|
||||
var result = normalizeSortRequest(
|
||||
[{ someField: 'desc'}]
|
||||
);
|
||||
it('should make plain string sort into the more verbose format', function () {
|
||||
var result = normalizeSortRequest([{ someField: 'desc'}], indexPattern);
|
||||
expect(result).to.eql(normalizedSort);
|
||||
});
|
||||
|
||||
it('appends default sort options', function () {
|
||||
var result = normalizeSortRequest(
|
||||
[{
|
||||
someField: {
|
||||
order: 'desc',
|
||||
unmapped_type: 'boolean'
|
||||
}
|
||||
}]
|
||||
);
|
||||
it('should append default sort options', function () {
|
||||
var sortState = [{
|
||||
someField: {
|
||||
order: 'desc',
|
||||
unmapped_type: 'boolean'
|
||||
}
|
||||
}];
|
||||
var result = normalizeSortRequest(sortState, indexPattern);
|
||||
expect(result).to.eql(normalizedSort);
|
||||
});
|
||||
|
||||
it('should enable script based sorting', function () {
|
||||
var fieldName = 'script string';
|
||||
var direction = 'desc';
|
||||
var indexField = indexPattern.fields.byName[fieldName];
|
||||
|
||||
var sortState = {};
|
||||
sortState[fieldName] = direction;
|
||||
normalizedSort = {
|
||||
_script: {
|
||||
script: indexField.script,
|
||||
type: indexField.type,
|
||||
order: direction
|
||||
}
|
||||
};
|
||||
|
||||
var result = normalizeSortRequest(sortState, indexPattern);
|
||||
expect(result).to.eql([normalizedSort]);
|
||||
|
||||
sortState[fieldName] = { order: direction };
|
||||
result = normalizeSortRequest([sortState], indexPattern);
|
||||
expect(result).to.eql([normalizedSort]);
|
||||
});
|
||||
|
||||
it('should use script based sorting only on sortable types', function () {
|
||||
var fieldName = 'script murmur3';
|
||||
var direction = 'asc';
|
||||
var indexField = indexPattern.fields.byName[fieldName];
|
||||
|
||||
var sortState = {};
|
||||
sortState[fieldName] = direction;
|
||||
normalizedSort = {};
|
||||
normalizedSort[fieldName] = {
|
||||
order: direction,
|
||||
unmapped_type: 'boolean'
|
||||
};
|
||||
var result = normalizeSortRequest([sortState], indexPattern);
|
||||
|
||||
expect(result).to.eql([normalizedSort]);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,15 +1,16 @@
|
|||
define(function (require) {
|
||||
var getSort = require('components/doc_table/lib/get_sort');
|
||||
var indexPattern =
|
||||
var defaultSort = {time: 'desc'};
|
||||
var indexPattern;
|
||||
|
||||
describe('docTable', function () {
|
||||
beforeEach(module('kibana'));
|
||||
|
||||
beforeEach(inject(function (Private, _$rootScope_, Promise) {
|
||||
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
|
||||
}));
|
||||
|
||||
describe('getSort function', function () {
|
||||
|
||||
beforeEach(module('kibana'));
|
||||
|
||||
beforeEach(inject(function (Private, _$rootScope_, Promise) {
|
||||
indexPattern = Private(require('fixtures/stubbed_logstash_index_pattern'));
|
||||
}));
|
||||
|
||||
it('should be a function', function () {
|
||||
expect(getSort).to.be.a(Function);
|
||||
});
|
||||
|
@ -22,17 +23,17 @@ define(function (require) {
|
|||
});
|
||||
|
||||
it('should sort by the default when passed an unsortable field', function () {
|
||||
expect(getSort(['_id', 'asc'], indexPattern)).to.eql({time: 'desc'});
|
||||
expect(getSort(['lol_nope', 'asc'], indexPattern)).to.eql({time: 'desc'});
|
||||
expect(getSort(['_id', 'asc'], indexPattern)).to.eql(defaultSort);
|
||||
expect(getSort(['lol_nope', 'asc'], indexPattern)).to.eql(defaultSort);
|
||||
|
||||
delete indexPattern.timeFieldName;
|
||||
expect(getSort(['_id', 'asc'], indexPattern)).to.eql({_score: 'desc'});
|
||||
});
|
||||
|
||||
it('should sort in reverse chrono order otherwise on time based patterns', function () {
|
||||
expect(getSort([], indexPattern)).to.eql({time: 'desc'});
|
||||
expect(getSort(['foo'], indexPattern)).to.eql({time: 'desc'});
|
||||
expect(getSort({foo: 'bar'}, indexPattern)).to.eql({time: 'desc'});
|
||||
expect(getSort([], indexPattern)).to.eql(defaultSort);
|
||||
expect(getSort(['foo'], indexPattern)).to.eql(defaultSort);
|
||||
expect(getSort({foo: 'bar'}, indexPattern)).to.eql(defaultSort);
|
||||
});
|
||||
|
||||
it('should sort by score on non-time patterns', function () {
|
||||
|
@ -42,7 +43,16 @@ define(function (require) {
|
|||
expect(getSort(['foo'], indexPattern)).to.eql({_score: 'desc'});
|
||||
expect(getSort({foo: 'bar'}, indexPattern)).to.eql({_score: 'desc'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSort.array function', function () {
|
||||
it('should have an array method', function () {
|
||||
expect(getSort.array).to.be.a(Function);
|
||||
});
|
||||
|
||||
it('should return an array for sortable fields', function () {
|
||||
expect(getSort.array(['bytes', 'desc'], indexPattern)).to.eql([ 'bytes', 'desc' ]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue