-
Notifications
You must be signed in to change notification settings - Fork 8k
/
normalize_sort_request.ts
84 lines (77 loc) · 2.94 KB
/
normalize_sort_request.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { estypes } from '@elastic/elasticsearch';
import type { DataView } from '@kbn/data-views-plugin/common';
import { EsQuerySortValue } from './types';
type FieldSortOptions = estypes.FieldSort &
estypes.ScoreSort &
estypes.GeoDistanceSort &
Omit<estypes.ScriptSort, 'script'> & {
script?: estypes.ScriptSort['script'];
};
export function normalizeSortRequest(
sortObject: EsQuerySortValue | EsQuerySortValue[],
indexPattern: DataView | string | undefined,
defaultSortOptions: FieldSortOptions | string = {}
) {
const sortArray: EsQuerySortValue[] = Array.isArray(sortObject) ? sortObject : [sortObject];
return sortArray.map(function (sortable) {
return normalize(sortable, indexPattern, defaultSortOptions);
});
}
/**
* Normalize the sort description to the more verbose format (e.g. { someField: "desc" } into
* { someField: { "order": "desc"}}), and convert sorts on scripted fields into the proper script
* for Elasticsearch. Mix in the default options according to the advanced settings.
*/
function normalize(
sortable: EsQuerySortValue,
indexPattern: DataView | string | undefined,
defaultSortOptions: FieldSortOptions | string
) {
const [[sortField, sortOrder]] = Object.entries(sortable);
const order = typeof sortOrder === 'object' ? sortOrder : { order: sortOrder };
if (indexPattern && typeof indexPattern !== 'string') {
const indexField = indexPattern.fields.find(({ name }) => name === sortField);
if (indexField && indexField.scripted && indexField.sortable) {
return {
_script: {
script: {
source: indexField.script,
lang: indexField.lang,
},
type: castSortType(indexField.type),
...order,
},
};
}
}
// FIXME: for unknown reason on the server this setting is serialized
// https://github.com/elastic/kibana/issues/89902
if (typeof defaultSortOptions === 'string') {
defaultSortOptions = JSON.parse(defaultSortOptions) as FieldSortOptions;
}
// Don't include unmapped_type for _score field
// eslint-disable-next-line @typescript-eslint/naming-convention
const { unmapped_type, ...otherSortOptions } = defaultSortOptions;
return {
[sortField]: {
...order,
...(sortField === '_score' ? otherSortOptions : defaultSortOptions),
},
};
}
// The ES API only supports sort scripts of type 'number' and 'string'
function castSortType(type: string) {
if (['number'].includes(type)) {
return 'number';
} else if (['string', 'boolean'].includes(type)) {
return 'string';
}
throw new Error(`Unsupported script sort type: ${type}`);
}