Sort server-side in SavedObject export (#55128)

Signed-off-by: Tyler Smalley <tyler.smalley@elastic.co>
This commit is contained in:
Tyler Smalley 2020-01-28 11:55:08 -08:00 committed by GitHub
parent 265c079a8a
commit ff37dd1c25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 13 deletions

View file

@ -108,8 +108,6 @@ describe('getSortedObjectsForExport()', () => {
"namespace": undefined,
"perPage": 500,
"search": undefined,
"sortField": "_id",
"sortOrder": "asc",
"type": Array [
"index-pattern",
"search",
@ -256,8 +254,6 @@ describe('getSortedObjectsForExport()', () => {
"namespace": undefined,
"perPage": 500,
"search": "foo",
"sortField": "_id",
"sortOrder": "asc",
"type": Array [
"index-pattern",
"search",
@ -345,8 +341,6 @@ describe('getSortedObjectsForExport()', () => {
"namespace": "foo",
"perPage": 500,
"search": undefined,
"sortField": "_id",
"sortOrder": "asc",
"type": Array [
"index-pattern",
"search",
@ -399,6 +393,79 @@ describe('getSortedObjectsForExport()', () => {
).rejects.toThrowErrorMatchingInlineSnapshot(`"Can't export more than 1 objects"`);
});
test('sorts objects within type', async () => {
savedObjectsClient.find.mockResolvedValueOnce({
total: 3,
per_page: 10000,
page: 1,
saved_objects: [
{
id: '3',
type: 'index-pattern',
attributes: {
name: 'baz',
},
references: [],
},
{
id: '1',
type: 'index-pattern',
attributes: {
name: 'foo',
},
references: [],
},
{
id: '2',
type: 'index-pattern',
attributes: {
name: 'bar',
},
references: [],
},
],
});
const exportStream = await getSortedObjectsForExport({
exportSizeLimit: 10000,
savedObjectsClient,
types: ['index-pattern'],
});
const response = await readStreamToCompletion(exportStream);
expect(response).toMatchInlineSnapshot(`
Array [
Object {
"attributes": Object {
"name": "foo",
},
"id": "1",
"references": Array [],
"type": "index-pattern",
},
Object {
"attributes": Object {
"name": "bar",
},
"id": "2",
"references": Array [],
"type": "index-pattern",
},
Object {
"attributes": Object {
"name": "baz",
},
"id": "3",
"references": Array [],
"type": "index-pattern",
},
Object {
"exportedCount": 3,
"missingRefCount": 0,
"missingReferences": Array [],
},
]
`);
});
test('exports selected objects and sorts them', async () => {
savedObjectsClient.bulkGet.mockResolvedValueOnce({
saved_objects: [

View file

@ -19,7 +19,7 @@
import Boom from 'boom';
import { createListStream } from '../../../../legacy/utils/streams';
import { SavedObjectsClientContract } from '../types';
import { SavedObjectsClientContract, SavedObject } from '../types';
import { fetchNestedDependencies } from './inject_nested_depdendencies';
import { sortObjects } from './sort_objects';
@ -105,15 +105,17 @@ async function fetchObjectsToExport({
const findResponse = await savedObjectsClient.find({
type: types,
search,
sortField: '_id',
sortOrder: 'asc',
perPage: exportSizeLimit,
namespace,
});
if (findResponse.total > exportSizeLimit) {
throw Boom.badRequest(`Can't export more than ${exportSizeLimit} objects`);
}
return findResponse.saved_objects;
// sorts server-side by _id, since it's only available in fielddata
return findResponse.saved_objects.sort((a: SavedObject, b: SavedObject) =>
a.id > b.id ? 1 : -1
);
} else {
throw Boom.badRequest('Either `type` or `objects` are required.');
}
@ -137,14 +139,17 @@ export async function getSortedObjectsForExport({
exportSizeLimit,
namespace,
});
let exportedObjects = [...rootObjects];
let exportedObjects = [];
let missingReferences: SavedObjectsExportResultDetails['missingReferences'] = [];
if (includeReferencesDeep) {
const fetchResult = await fetchNestedDependencies(rootObjects, savedObjectsClient, namespace);
exportedObjects = fetchResult.objects;
exportedObjects = sortObjects(fetchResult.objects);
missingReferences = fetchResult.missingRefs;
} else {
exportedObjects = sortObjects(rootObjects);
}
exportedObjects = sortObjects(exportedObjects);
const exportDetails: SavedObjectsExportResultDetails = {
exportedCount: exportedObjects.length,
missingRefCount: missingReferences.length,