Skip to content

Commit ac0953e

Browse files
authored
[Discover] Change default sort handling for index patterns without timefield (#54427)
Default sort is no longer in state. There's now a separate function to provide default sort for ES and UI, in case the user didn't actively select a field to sort by
1 parent 1e91775 commit ac0953e

File tree

12 files changed

+103
-45
lines changed

12 files changed

+103
-45
lines changed

src/legacy/core_plugins/kibana/public/discover/__tests__/doc_table/lib/get_sort.js

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import ngMock from 'ng_mock';
2323
import { getSort } from '../../../np_ready/angular/doc_table/lib/get_sort';
2424
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
2525

26-
const defaultSort = [{ time: 'desc' }];
2726
let indexPattern;
2827

2928
describe('docTable', function() {
@@ -51,26 +50,26 @@ describe('docTable', function() {
5150
expect(getSort([{ bytes: 'desc' }], indexPattern)).to.eql([{ bytes: 'desc' }]);
5251
});
5352

54-
it('should sort by the default when passed an unsortable field', function() {
55-
expect(getSort(['non-sortable', 'asc'], indexPattern)).to.eql(defaultSort);
56-
expect(getSort(['lol_nope', 'asc'], indexPattern)).to.eql(defaultSort);
53+
it('should return an empty array when passed an unsortable field', function() {
54+
expect(getSort(['non-sortable', 'asc'], indexPattern)).to.eql([]);
55+
expect(getSort(['lol_nope', 'asc'], indexPattern)).to.eql([]);
5756

5857
delete indexPattern.timeFieldName;
59-
expect(getSort(['non-sortable', 'asc'], indexPattern)).to.eql([{ _score: 'desc' }]);
58+
expect(getSort(['non-sortable', 'asc'], indexPattern)).to.eql([]);
6059
});
6160

62-
it('should sort in reverse chrono order otherwise on time based patterns', function() {
63-
expect(getSort([], indexPattern)).to.eql(defaultSort);
64-
expect(getSort(['foo'], indexPattern)).to.eql(defaultSort);
65-
expect(getSort({ foo: 'bar' }, indexPattern)).to.eql(defaultSort);
61+
it('should return an empty array ', function() {
62+
expect(getSort([], indexPattern)).to.eql([]);
63+
expect(getSort(['foo'], indexPattern)).to.eql([]);
64+
expect(getSort({ foo: 'bar' }, indexPattern)).to.eql([]);
6665
});
6766

68-
it('should sort by score on non-time patterns', function() {
67+
it('should return an empty array on non-time patterns', function() {
6968
delete indexPattern.timeFieldName;
7069

71-
expect(getSort([], indexPattern)).to.eql([{ _score: 'desc' }]);
72-
expect(getSort(['foo'], indexPattern)).to.eql([{ _score: 'desc' }]);
73-
expect(getSort({ foo: 'bar' }, indexPattern)).to.eql([{ _score: 'desc' }]);
70+
expect(getSort([], indexPattern)).to.eql([]);
71+
expect(getSort(['foo'], indexPattern)).to.eql([]);
72+
expect(getSort({ foo: 'bar' }, indexPattern)).to.eql([]);
7473
});
7574
});
7675

@@ -87,19 +86,19 @@ describe('docTable', function() {
8786
expect(getSort.array([{ bytes: 'desc' }], indexPattern)).to.eql([['bytes', 'desc']]);
8887
});
8988

90-
it('should sort by the default when passed an unsortable field', function() {
91-
expect(getSort.array([{ 'non-sortable': 'asc' }], indexPattern)).to.eql([['time', 'desc']]);
92-
expect(getSort.array([{ lol_nope: 'asc' }], indexPattern)).to.eql([['time', 'desc']]);
89+
it('should sort by an empty array when an unsortable field is given', function() {
90+
expect(getSort.array([{ 'non-sortable': 'asc' }], indexPattern)).to.eql([]);
91+
expect(getSort.array([{ lol_nope: 'asc' }], indexPattern)).to.eql([]);
9392

9493
delete indexPattern.timeFieldName;
95-
expect(getSort.array([{ 'non-sortable': 'asc' }], indexPattern)).to.eql([['_score', 'desc']]);
94+
expect(getSort.array([{ 'non-sortable': 'asc' }], indexPattern)).to.eql([]);
9695
});
9796

98-
it('should sort by the default when passed an empty sort', () => {
99-
expect(getSort.array([], indexPattern)).to.eql([['time', 'desc']]);
97+
it('should return an empty array when passed an empty sort array', () => {
98+
expect(getSort.array([], indexPattern)).to.eql([]);
10099

101100
delete indexPattern.timeFieldName;
102-
expect(getSort.array([], indexPattern)).to.eql([['_score', 'desc']]);
101+
expect(getSort.array([], indexPattern)).to.eql([]);
103102
});
104103
});
105104
});

src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,14 @@ function discoverController(
486486

487487
const { searchFields, selectFields } = await getSharingDataFields();
488488
searchSource.setField('fields', searchFields);
489-
searchSource.setField('sort', getSortForSearchSource($state.sort, $scope.indexPattern));
489+
searchSource.setField(
490+
'sort',
491+
getSortForSearchSource(
492+
$state.sort,
493+
$scope.indexPattern,
494+
config.get('discover:sort:defaultOrder')
495+
)
496+
);
490497
searchSource.setField('highlight', null);
491498
searchSource.setField('highlightAll', null);
492499
searchSource.setField('aggs', null);
@@ -517,11 +524,7 @@ function discoverController(
517524
language:
518525
localStorage.get('kibana.userQueryLanguage') || config.get('search:queryLanguage'),
519526
},
520-
sort: getSort.array(
521-
savedSearch.sort,
522-
$scope.indexPattern,
523-
config.get('discover:sort:defaultOrder')
524-
),
527+
sort: getSort.array(savedSearch.sort, $scope.indexPattern),
525528
columns:
526529
savedSearch.columns.length > 0 ? savedSearch.columns : config.get('defaultColumns').slice(),
527530
index: $scope.indexPattern.id,
@@ -934,7 +937,10 @@ function discoverController(
934937
const { indexPattern, searchSource } = $scope;
935938
searchSource
936939
.setField('size', $scope.opts.sampleSize)
937-
.setField('sort', getSortForSearchSource($state.sort, indexPattern))
940+
.setField(
941+
'sort',
942+
getSortForSearchSource($state.sort, indexPattern, config.get('discover:sort:defaultOrder'))
943+
)
938944
.setField('query', !$state.query ? null : $state.query)
939945
.setField('filter', filterManager.getFilters());
940946
});

src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export function createTableHeaderDirective(reactDirective: any, config: IUiSetti
3737
{
3838
hideTimeColumn: config.get('doc_table:hideTimeColumn'),
3939
isShortDots: config.get('shortDots:enable'),
40+
defaultSortOrder: config.get('discover:sort:defaultOrder'),
4041
}
4142
);
4243
}

src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/helpers.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { IndexPattern } from '../../../../../kibana_services';
2020
// @ts-ignore
2121
import { shortenDottedString } from '../../../../../../../common/utils/shorten_dotted_string';
2222

23-
export type SortOrder = [string, 'asc' | 'desc'];
23+
export type SortOrder = [string, string];
2424
export interface ColumnProps {
2525
name: string;
2626
displayName: string;

src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ function getMockProps(props = {}) {
5959
indexPattern: getMockIndexPattern(),
6060
hideTimeColumn: false,
6161
columns: ['first', 'middle', 'last'],
62+
defaultSortOrder: 'desc',
6263
sortOrder: [['time', 'asc']] as SortOrder[],
6364
isShortDots: true,
6465
onRemoveColumn: jest.fn(),

src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ import { IndexPattern } from '../../../../../kibana_services';
2121
// @ts-ignore
2222
import { TableHeaderColumn } from './table_header_column';
2323
import { SortOrder, getDisplayedColumns } from './helpers';
24+
import { getDefaultSort } from '../../lib/get_default_sort';
2425

2526
interface Props {
2627
columns: string[];
28+
defaultSortOrder: string;
2729
hideTimeColumn: boolean;
2830
indexPattern: IndexPattern;
2931
isShortDots: boolean;
@@ -35,6 +37,7 @@ interface Props {
3537

3638
export function TableHeader({
3739
columns,
40+
defaultSortOrder,
3841
hideTimeColumn,
3942
indexPattern,
4043
isShortDots,
@@ -53,7 +56,9 @@ export function TableHeader({
5356
<TableHeaderColumn
5457
key={col.name}
5558
{...col}
56-
sortOrder={sortOrder}
59+
sortOrder={
60+
sortOrder.length ? sortOrder : getDefaultSort(indexPattern, defaultSortOrder)
61+
}
5762
onMoveColumn={onMoveColumn}
5863
onRemoveColumn={onRemoveColumn}
5964
onChangeSortOrder={onChangeSortOrder}

src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/components/table_header/table_header_column.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ interface Props {
3434
sortOrder: SortOrder[];
3535
}
3636

37-
const sortDirectionToIcon = {
37+
const sortDirectionToIcon: Record<string, string> = {
3838
desc: 'fa fa-sort-down',
3939
asc: 'fa fa-sort-up',
4040
'': 'fa fa-sort',
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import { IndexPattern } from '../../../../kibana_services';
20+
// @ts-ignore
21+
import { isSortable } from './get_sort';
22+
import { SortOrder } from '../components/table_header/helpers';
23+
24+
/**
25+
* use in case the user didn't manually sort.
26+
* the default sort is returned depending of the index pattern
27+
*/
28+
export function getDefaultSort(
29+
indexPattern: IndexPattern,
30+
defaultSortOrder: string = 'desc'
31+
): SortOrder[] {
32+
if (indexPattern.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) {
33+
return [[indexPattern.timeFieldName, defaultSortOrder]];
34+
} else {
35+
return [['_score', defaultSortOrder]];
36+
}
37+
}

src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
import _ from 'lodash';
2121

22-
function isSortable(field, indexPattern) {
22+
export function isSortable(field, indexPattern) {
2323
return indexPattern.fields.getByName(field) && indexPattern.fields.getByName(field).sortable;
2424
}
2525

@@ -41,23 +41,20 @@ function createSortObject(sortPair, indexPattern) {
4141
* @param {object} indexPattern used for determining default sort
4242
* @returns {object} a sort object suitable for returning to elasticsearch
4343
*/
44-
export function getSort(sort, indexPattern, defaultSortOrder = 'desc') {
44+
export function getSort(sort, indexPattern) {
4545
let sortObjects;
4646
if (Array.isArray(sort)) {
4747
sortObjects = _.compact(sort.map(sortPair => createSortObject(sortPair, indexPattern)));
4848
}
4949

5050
if (!_.isEmpty(sortObjects)) {
5151
return sortObjects;
52-
} else if (indexPattern.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) {
53-
return [{ [indexPattern.timeFieldName]: defaultSortOrder }];
54-
} else {
55-
return [{ _score: 'desc' }];
5652
}
53+
return [];
5754
}
5855

59-
getSort.array = function(sort, indexPattern, defaultSortOrder) {
60-
return getSort(sort, indexPattern, defaultSortOrder).map(sortPair =>
56+
getSort.array = function(sort, indexPattern) {
57+
return getSort(sort, indexPattern).map(sortPair =>
6158
_(sortPair)
6259
.pairs()
6360
.pop()

src/legacy/core_plugins/kibana/public/discover/np_ready/angular/doc_table/lib/get_sort_for_search_source.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,24 @@
1919
import { IndexPattern } from '../../../../kibana_services';
2020
import { SortOrder } from '../components/table_header/helpers';
2121
import { getSort } from './get_sort';
22+
import { getDefaultSort } from './get_default_sort';
2223

2324
/**
24-
* prepares sort for search source, that's sending the request to ES
25-
* handles the special case when there's sorting by date_nanos typed fields
26-
* the addon of the numeric_type guarantees the right sort order
27-
* when there are indices with date and indices with date_nanos field
25+
* Prepares sort for search source, that's sending the request to ES
26+
* - Adds default sort if necessary
27+
* - Handles the special case when there's sorting by date_nanos typed fields
28+
* the addon of the numeric_type guarantees the right sort order
29+
* when there are indices with date and indices with date_nanos field
2830
*/
29-
export function getSortForSearchSource(sort?: SortOrder[], indexPattern?: IndexPattern) {
31+
export function getSortForSearchSource(
32+
sort?: SortOrder[],
33+
indexPattern?: IndexPattern,
34+
defaultDirection: 'asc' | 'desc' = 'desc'
35+
) {
3036
if (!sort || !indexPattern) {
3137
return [];
38+
} else if (Array.isArray(sort) && sort.length === 0) {
39+
sort = getDefaultSort(indexPattern, defaultDirection);
3240
}
3341
const { timeFieldName } = indexPattern;
3442
return getSort(sort, indexPattern).map((sortPair: Record<string, string>) => {

0 commit comments

Comments
 (0)