diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.md index 50b28b1ba0a237..ebd0a99531755b 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.md @@ -26,7 +26,7 @@ export interface SavedObjectsFindOptions | [rootSearchFields](./kibana-plugin-core-public.savedobjectsfindoptions.rootsearchfields.md) | string[] | The fields to perform the parsed query against. Unlike the searchFields argument, these are expected to be root fields and will not be modified. If used in conjunction with searchFields, both are concatenated together. | | [search](./kibana-plugin-core-public.savedobjectsfindoptions.search.md) | string | Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String query argument for more information | | [searchFields](./kibana-plugin-core-public.savedobjectsfindoptions.searchfields.md) | string[] | The fields to perform the parsed query against. See Elasticsearch Simple Query String fields argument for more information | -| [sortField](./kibana-plugin-core-public.savedobjectsfindoptions.sortfield.md) | string | string[] | | -| [sortOrder](./kibana-plugin-core-public.savedobjectsfindoptions.sortorder.md) | string | string[] | | +| [sortField](./kibana-plugin-core-public.savedobjectsfindoptions.sortfield.md) | string | | +| [sortOrder](./kibana-plugin-core-public.savedobjectsfindoptions.sortorder.md) | string | | | [type](./kibana-plugin-core-public.savedobjectsfindoptions.type.md) | string | string[] | | diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.sortfield.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.sortfield.md index 4336b01d6bd8cf..7b5072c0e19dfa 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.sortfield.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.sortfield.md @@ -7,5 +7,5 @@ Signature: ```typescript -sortField?: string | string[]; +sortField?: string; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.sortorder.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.sortorder.md index 68540d6607b8f9..3834c802fa1845 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.sortorder.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsfindoptions.sortorder.md @@ -7,5 +7,5 @@ Signature: ```typescript -sortOrder?: string | string[]; +sortOrder?: string; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.md index 82225607a7955e..15a9d99b3d062e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.md @@ -26,7 +26,7 @@ export interface SavedObjectsFindOptions | [rootSearchFields](./kibana-plugin-core-server.savedobjectsfindoptions.rootsearchfields.md) | string[] | The fields to perform the parsed query against. Unlike the searchFields argument, these are expected to be root fields and will not be modified. If used in conjunction with searchFields, both are concatenated together. | | [search](./kibana-plugin-core-server.savedobjectsfindoptions.search.md) | string | Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String query argument for more information | | [searchFields](./kibana-plugin-core-server.savedobjectsfindoptions.searchfields.md) | string[] | The fields to perform the parsed query against. See Elasticsearch Simple Query String fields argument for more information | -| [sortField](./kibana-plugin-core-server.savedobjectsfindoptions.sortfield.md) | string | string[] | | -| [sortOrder](./kibana-plugin-core-server.savedobjectsfindoptions.sortorder.md) | string | string[] | | +| [sortField](./kibana-plugin-core-server.savedobjectsfindoptions.sortfield.md) | string | | +| [sortOrder](./kibana-plugin-core-server.savedobjectsfindoptions.sortorder.md) | string | | | [type](./kibana-plugin-core-server.savedobjectsfindoptions.type.md) | string | string[] | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.sortfield.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.sortfield.md index 2c8657ba7319cf..1dffe996d5726c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.sortfield.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.sortfield.md @@ -7,5 +7,5 @@ Signature: ```typescript -sortField?: string | string[]; +sortField?: string; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.sortorder.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.sortorder.md index 23dabdf1797fc0..d247b9e38e4489 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.sortorder.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsfindoptions.sortorder.md @@ -7,5 +7,5 @@ Signature: ```typescript -sortOrder?: string | string[]; +sortOrder?: string; ``` diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index fc8a94314631fa..8dd4744034cab5 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -1205,9 +1205,9 @@ export interface SavedObjectsFindOptions { search?: string; searchFields?: string[]; // (undocumented) - sortField?: string | string[]; + sortField?: string; // (undocumented) - sortOrder?: string | string[]; + sortOrder?: string; // (undocumented) type: string | string[]; } diff --git a/src/core/server/saved_objects/service/lib/search_dsl/__snapshots__/sorting_params.test.ts.snap b/src/core/server/saved_objects/service/lib/search_dsl/__snapshots__/sorting_params.test.ts.snap new file mode 100644 index 00000000000000..8226b1c6695b47 --- /dev/null +++ b/src/core/server/saved_objects/service/lib/search_dsl/__snapshots__/sorting_params.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`searchDsl/getSortParams sort with direction sortField is non-root multi-field with multiple types returns correct params 1`] = `"Unable to sort multiple types by field title.raw, not a root property"`; + +exports[`searchDsl/getSortParams sort with direction sortFields is non-root simple property with multiple types returns correct params 1`] = `"Unable to sort multiple types by field title, not a root property"`; + +exports[`searchDsl/getSortParams sortField no direction sortField is not-root multi-field with multiple types returns correct params 1`] = `"Unable to sort multiple types by field title.raw, not a root property"`; + +exports[`searchDsl/getSortParams sortField no direction sortField is simple non-root property with multiple types returns correct params 1`] = `"Unable to sort multiple types by field title, not a root property"`; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts index 4787a227438b1c..62e629ad33cc88 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.test.ts @@ -46,17 +46,12 @@ describe('getSearchDsl', () => { }); }).toThrowError(/type must be specified/); }); - - it('throws when sortOrder is defined and sortField is undefined', () => { - expect(() => { - getSearchDsl(mappings, registry, { type: 'foo', sortOrder: 'desc' }); - }).toThrowError(/sortOrder requires a sortField/); - }); - - it('throws when sortOrder length is greater than sortField length', () => { + it('throws when sortOrder without sortField', () => { expect(() => { - const options = { type: 'foo', sortField: ['bar'], sortOrder: ['baz', 'qux'] }; - getSearchDsl(mappings, registry, options); + getSearchDsl(mappings, registry, { + type: 'foo', + sortOrder: 'desc', + }); }).toThrowError(/sortOrder requires a sortField/); }); }); @@ -91,30 +86,22 @@ describe('getSearchDsl', () => { }); }); - describe('passes (mappings, type, sortField, sortOrder) to getSortingParams', () => { - it('with string type and undefined sortField/sortOrder', () => { - getSortingParams.mockReturnValue({}); - - getSearchDsl(mappings, registry, { type: 'foo' }); - expect(getSortingParams).toHaveBeenCalledTimes(1); - expect(getSortingParams).toHaveBeenCalledWith(mappings, 'foo', [], []); - }); - - it('with strings', () => { - getSortingParams.mockReturnValue({}); - - getSearchDsl(mappings, registry, { type: 'foo', sortField: 'bar', sortOrder: 'baz' }); - expect(getSortingParams).toHaveBeenCalledTimes(1); - expect(getSortingParams).toHaveBeenCalledWith(mappings, 'foo', ['bar'], ['baz']); - }); - - it('with string arrays', () => { - getSortingParams.mockReturnValue({}); + it('passes (mappings, type, sortField, sortOrder) to getSortingParams', () => { + getSortingParams.mockReturnValue({}); + const opts = { + type: 'foo', + sortField: 'bar', + sortOrder: 'baz', + }; - getSearchDsl(mappings, registry, { type: ['foo'], sortField: ['bar'], sortOrder: ['baz'] }); - expect(getSortingParams).toHaveBeenCalledTimes(1); - expect(getSortingParams).toHaveBeenCalledWith(mappings, ['foo'], ['bar'], ['baz']); - }); + getSearchDsl(mappings, registry, opts); + expect(getSortingParams).toHaveBeenCalledTimes(1); + expect(getSortingParams).toHaveBeenCalledWith( + mappings, + opts.type, + opts.sortField, + opts.sortOrder + ); }); it('returns combination of getQueryParams and getSortingParams', () => { diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts index f0fb25abb8e094..ddf20606800c8e 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts @@ -32,8 +32,8 @@ interface GetSearchDslOptions { defaultSearchOperator?: string; searchFields?: string[]; rootSearchFields?: string[]; - sortField?: string | string[]; - sortOrder?: string | string[]; + sortField?: string; + sortOrder?: string; namespaces?: string[]; hasReference?: { type: string; @@ -64,10 +64,7 @@ export function getSearchDsl( throw Boom.notAcceptable('type must be specified'); } - const sortFields = sortField ? (Array.isArray(sortField) ? sortField : [sortField]) : []; - const sortOrders = sortOrder ? (Array.isArray(sortOrder) ? sortOrder : [sortOrder]) : []; - - if (sortOrders.length > sortFields.length) { + if (sortOrder && !sortField) { throw Boom.notAcceptable('sortOrder requires a sortField'); } @@ -84,6 +81,6 @@ export function getSearchDsl( hasReference, kueryNode, }), - ...getSortingParams(mappings, type, sortFields, sortOrders), + ...getSortingParams(mappings, type, sortField, sortOrder), }; } diff --git a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts index dafa82c62955d8..c7a4b7df065472 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts @@ -29,9 +29,6 @@ const MAPPINGS = { }, }, }, - updated_at: { - type: 'date', - }, pending: { properties: { title: { @@ -67,187 +64,174 @@ const MAPPINGS = { }; describe('searchDsl/getSortParams', () => { - describe('errors', () => { - it('throws an error when multiple types are used and a sort field is not a valid root property', () => { - expect(() => - getSortingParams(MAPPINGS, ['saved', 'pending'], ['title'], []) - ).toThrowErrorMatchingInlineSnapshot( - `"Unable to sort multiple types by field title, not a root property"` - ); - }); - - it('throws an error a single type is used and a sort field is not a valid simple property', () => { - expect(() => - getSortingParams(MAPPINGS, ['saved'], ['type'], []) - ).toThrowErrorMatchingInlineSnapshot(`"Unknown sort field type"`); - expect(() => - getSortingParams(MAPPINGS, ['saved'], ['foo'], []) - ).toThrowErrorMatchingInlineSnapshot(`"Unknown sort field foo"`); + describe('type, no sortField', () => { + it('returns no params', () => { + expect(getSortingParams(MAPPINGS, 'pending')).toEqual({}); }); }); - describe('results', () => { - it('returns an empty object when `sortFields` is empty', () => { - expect(getSortingParams(MAPPINGS, 'pending', [], [])).toEqual({}); + describe('type, order, no sortField', () => { + it('returns no params', () => { + expect(getSortingParams(MAPPINGS, 'saved', undefined, 'desc')).toEqual({}); }); + }); - describe('top-level fields', () => { - const type = 'saved'; // specific type doesn't matter for these test cases, it just needs to be valid - - it('single sort field without a sort order', () => { - const { sort } = getSortingParams(MAPPINGS, type, ['_id'], []); - expect(sort).toEqual([{ _id: { order: undefined } }]); - }); - - it('single sort field with a single sort order', () => { - const { sort } = getSortingParams(MAPPINGS, type, ['_id'], ['foo']); - expect(sort).toEqual([{ _id: { order: 'foo' } }]); - }); - - it('single sort field with multiple sort orders', () => { - const { sort } = getSortingParams(MAPPINGS, type, ['_id'], ['foo', 'bar']); - expect(sort).toEqual([{ _id: { order: 'foo' } }]); - }); - - it('multiple sort fields without a sort order', () => { - const { sort } = getSortingParams(MAPPINGS, type, ['_id', '_score'], []); - expect(sort).toEqual([{ _id: { order: undefined } }, { _score: { order: undefined } }]); - }); - - it('multiple sort fields with a single sort order', () => { - const { sort } = getSortingParams(MAPPINGS, type, ['_id', '_score'], ['foo']); - expect(sort).toEqual([{ _id: { order: 'foo' } }, { _score: { order: undefined } }]); - }); - - it('multiple sort fields with multiple sort orders', () => { - const { sort } = getSortingParams(MAPPINGS, type, ['_id', '_score'], ['foo', 'bar']); - expect(sort).toEqual([{ _id: { order: 'foo' } }, { _score: { order: 'bar' } }]); + describe('sortField no direction', () => { + describe('sortField is simple property with single type', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, 'saved', 'title')).toEqual({ + sort: [ + { + 'saved.title': { + order: undefined, + unmapped_type: 'text', + }, + }, + ], + }); }); }); - - describe('root properties', () => { - const types = ['saved', 'pending']; - - it('single sort field without a sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['type'], []); - expect(sort).toEqual([{ type: { order: undefined, unmapped_type: 'text' } }]); - }); - - it('single sort field with a single sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['type'], ['foo']); - expect(sort).toEqual([{ type: { order: 'foo', unmapped_type: 'text' } }]); - }); - - it('single sort field with multiple sort orders', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['type'], ['foo', 'bar']); - expect(sort).toEqual([{ type: { order: 'foo', unmapped_type: 'text' } }]); - }); - - it('multiple sort fields without a sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['type', 'updated_at'], []); - expect(sort).toEqual([ - { type: { order: undefined, unmapped_type: 'text' } }, - { updated_at: { order: undefined, unmapped_type: 'date' } }, - ]); - }); - - it('multiple sort fields with a single sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['type', 'updated_at'], ['foo']); - expect(sort).toEqual([ - { type: { order: 'foo', unmapped_type: 'text' } }, - { updated_at: { order: undefined, unmapped_type: 'date' } }, - ]); + describe('sortField is simple root property with multiple types', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type')).toEqual({ + sort: [ + { + type: { + order: undefined, + unmapped_type: 'text', + }, + }, + ], + }); }); - - it('multiple sort fields with multiple sort orders', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['type', 'updated_at'], ['foo', 'bar']); - expect(sort).toEqual([ - { type: { order: 'foo', unmapped_type: 'text' } }, - { updated_at: { order: 'bar', unmapped_type: 'date' } }, - ]); + }); + describe('sortField is simple non-root property with multiple types', () => { + it('returns correct params', () => { + expect(() => + getSortingParams(MAPPINGS, ['saved', 'pending'], 'title') + ).toThrowErrorMatchingSnapshot(); }); }); - - describe('simple properties', () => { - const types = 'saved'; - - it('single sort field without a sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['title'], []); - expect(sort).toEqual([{ ['saved.title']: { order: undefined, unmapped_type: 'text' } }]); + describe('sortField is multi-field with single type', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, 'saved', 'title.raw')).toEqual({ + sort: [ + { + 'saved.title.raw': { + order: undefined, + unmapped_type: 'keyword', + }, + }, + ], + }); }); - - it('single sort field with a single sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['title'], ['foo']); - expect(sort).toEqual([{ ['saved.title']: { order: 'foo', unmapped_type: 'text' } }]); + }); + describe('sortField is multi-field with single type as array', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, ['saved'], 'title.raw')).toEqual({ + sort: [ + { + 'saved.title.raw': { + order: undefined, + unmapped_type: 'keyword', + }, + }, + ], + }); }); - - it('single sort field with multiple sort orders', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['title'], ['foo', 'bar']); - expect(sort).toEqual([{ ['saved.title']: { order: 'foo', unmapped_type: 'text' } }]); + }); + describe('sortField is root multi-field with multiple types', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type.raw')).toEqual({ + sort: [ + { + 'type.raw': { + order: undefined, + unmapped_type: 'keyword', + }, + }, + ], + }); }); - - it('multiple sort fields without a sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['title', 'obj.key1'], []); - expect(sort).toEqual([ - { ['saved.title']: { order: undefined, unmapped_type: 'text' } }, - { ['saved.obj.key1']: { order: undefined, unmapped_type: 'text' } }, - ]); + }); + describe('sortField is not-root multi-field with multiple types', () => { + it('returns correct params', () => { + expect(() => + getSortingParams(MAPPINGS, ['saved', 'pending'], 'title.raw') + ).toThrowErrorMatchingSnapshot(); }); + }); + }); - it('multiple sort fields with a single sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['title', 'obj.key1'], ['foo']); - expect(sort).toEqual([ - { ['saved.title']: { order: 'foo', unmapped_type: 'text' } }, - { ['saved.obj.key1']: { order: undefined, unmapped_type: 'text' } }, - ]); + describe('sort with direction', () => { + describe('sortField is simple property with single type', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, 'saved', 'title', 'desc')).toEqual({ + sort: [ + { + 'saved.title': { + order: 'desc', + unmapped_type: 'text', + }, + }, + ], + }); }); - - it('multiple sort fields with multiple sort orders', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['title', 'obj.key1'], ['foo', 'bar']); - expect(sort).toEqual([ - { ['saved.title']: { order: 'foo', unmapped_type: 'text' } }, - { ['saved.obj.key1']: { order: 'bar', unmapped_type: 'text' } }, - ]); + }); + describe('sortField is root simple property with multiple type', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type', 'desc')).toEqual({ + sort: [ + { + type: { + order: 'desc', + unmapped_type: 'text', + }, + }, + ], + }); }); }); - - describe('mixed properties, single type', () => { - const type = 'saved'; - - it('without a sort order', () => { - const { sort } = getSortingParams(MAPPINGS, type, ['_id', 'title'], []); - expect(sort).toEqual([ - { _id: { order: undefined } }, - { ['saved.title']: { order: undefined, unmapped_type: 'text' } }, - ]); + describe('sortFields is non-root simple property with multiple types', () => { + it('returns correct params', () => { + expect(() => + getSortingParams(MAPPINGS, ['saved', 'pending'], 'title', 'desc') + ).toThrowErrorMatchingSnapshot(); }); - - it('with multiple sort orders', () => { - const { sort } = getSortingParams(MAPPINGS, type, ['_id', 'title'], ['foo', 'bar']); - expect(sort).toEqual([ - { _id: { order: 'foo' } }, - { ['saved.title']: { order: 'bar', unmapped_type: 'text' } }, - ]); + }); + describe('sortField is multi-field with single type', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, 'saved', 'title.raw', 'asc')).toEqual({ + sort: [ + { + 'saved.title.raw': { + order: 'asc', + unmapped_type: 'keyword', + }, + }, + ], + }); }); }); - - describe('mixed properties, multiple types', () => { - const types = ['saved', 'pending']; - - it('without a sort order', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['_id', 'type'], []); - expect(sort).toEqual([ - { _id: { order: undefined } }, - { type: { order: undefined, unmapped_type: 'text' } }, - ]); + describe('sortField is root multi-field with multiple types', () => { + it('returns correct params', () => { + expect(getSortingParams(MAPPINGS, ['saved', 'pending'], 'type.raw', 'asc')).toEqual({ + sort: [ + { + 'type.raw': { + order: 'asc', + unmapped_type: 'keyword', + }, + }, + ], + }); }); - - it('with multiple sort orders', () => { - const { sort } = getSortingParams(MAPPINGS, types, ['_id', 'type'], ['foo', 'bar']); - expect(sort).toEqual([ - { _id: { order: 'foo' } }, - { type: { order: 'bar', unmapped_type: 'text' } }, - ]); + }); + describe('sortField is non-root multi-field with multiple types', () => { + it('returns correct params', () => { + expect(() => + getSortingParams(MAPPINGS, ['saved', 'pending'], 'title.raw', 'asc') + ).toThrowErrorMatchingSnapshot(); }); }); }); diff --git a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts index ae981d45f98423..f850954e843233 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts @@ -25,41 +25,62 @@ const TOP_LEVEL_FIELDS = ['_id', '_score']; export function getSortingParams( mappings: IndexMapping, type: string | string[], - sortFields: string[], - sortOrders: string[] + sortField?: string, + sortOrder?: string ) { - if (sortFields.length === 0) { + if (!sortField) { return {}; } const types = Array.isArray(type) ? type : [type]; - const sort = sortFields.map((sortField, i) => { - const sortOrder = sortOrders[i]; - - if (TOP_LEVEL_FIELDS.includes(sortField)) { - return { [sortField]: { order: sortOrder } }; - } + if (TOP_LEVEL_FIELDS.includes(sortField)) { + return { + sort: [ + { + [sortField]: { + order: sortOrder, + }, + }, + ], + }; + } - if (types.length > 1) { - const rootField = getProperty(mappings, sortField); - if (!rootField) { - throw Boom.badRequest( - `Unable to sort multiple types by field ${sortField}, not a root property` - ); - } - return { [sortField]: { order: sortOrder, unmapped_type: rootField.type } }; + if (types.length > 1) { + const rootField = getProperty(mappings, sortField); + if (!rootField) { + throw Boom.badRequest( + `Unable to sort multiple types by field ${sortField}, not a root property` + ); } - const [typeField] = types; - const key = `${typeField}.${sortField}`; - const field = getProperty(mappings, key); - if (!field) { - throw Boom.badRequest(`Unknown sort field ${sortField}`); - } + return { + sort: [ + { + [sortField]: { + order: sortOrder, + unmapped_type: rootField.type, + }, + }, + ], + }; + } - return { [key]: { order: sortOrder, unmapped_type: field.type } }; - }); + const [typeField] = types; + const key = `${typeField}.${sortField}`; + const field = getProperty(mappings, key); + if (!field) { + throw Boom.badRequest(`Unknown sort field ${sortField}`); + } - return { sort }; + return { + sort: [ + { + [key]: { + order: sortOrder, + unmapped_type: field.type, + }, + }, + ], + }; } diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index 8cd8e8a12d9718..7b3697173ef0da 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -70,8 +70,8 @@ export interface SavedObjectsFindOptions { type: string | string[]; page?: number; perPage?: number; - sortField?: string | string[]; - sortOrder?: string | string[]; + sortField?: string; + sortOrder?: string; /** * An array of fields to include in the results * @example diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index b4285c466245eb..44a0aa54c1c85c 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2314,9 +2314,9 @@ export interface SavedObjectsFindOptions { search?: string; searchFields?: string[]; // (undocumented) - sortField?: string | string[]; + sortField?: string; // (undocumented) - sortOrder?: string | string[]; + sortOrder?: string; // (undocumented) type: string | string[]; } diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 6cd0c891c2247f..38b618fb082b91 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -224,9 +224,7 @@ export class SavedObjectsTable extends Component !visibleTypes || visibleTypes.includes(type)), }; if (findOptions.type.length > 1) { - findOptions.sortField = ['type', '_id']; - } else { - findOptions.sortField = '_id'; + findOptions.sortField = 'type'; } try { diff --git a/src/plugins/saved_objects_management/server/routes/find.ts b/src/plugins/saved_objects_management/server/routes/find.ts index 2bb7a692eefcb1..0d88e6ec3f3b58 100644 --- a/src/plugins/saved_objects_management/server/routes/find.ts +++ b/src/plugins/saved_objects_management/server/routes/find.ts @@ -38,7 +38,7 @@ export const registerFindRoute = ( defaultSearchOperator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { defaultValue: 'OR', }), - sortField: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), + sortField: schema.maybe(schema.string()), hasReference: schema.maybe( schema.object({ type: schema.string(),