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 50b28b1ba0a2372..ebd0a99531755b2 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 4336b01d6bd8cf0..7b5072c0e19dfaa 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 68540d6607b8f95..3834c802fa18453 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 82225607a7955ef..15a9d99b3d062e7 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 2c8657ba7319cf3..1dffe996d5726ce 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 23dabdf1797fc0c..d247b9e38e44896 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 79a822b2736567e..e8a28c897b014b7 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -1316,9 +1316,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 000000000000000..8226b1c6695b47c --- /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 4787a227438b1c6..62e629ad33cc884 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 f0fb25abb8e094a..ddf20606800c8ee 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 dafa82c62955d85..c7a4b7df065472c 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 ae981d45f984239..f850954e8432331 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 8cd8e8a12d97184..7b3697173ef0da7 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 2c82c4d875a8b35..cb651043844c2ce 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2219,9 +2219,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 6cd0c891c2247f4..38b618fb082b916 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 2bb7a692eefcb15..0d88e6ec3f3b588 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(),