savedObjects: add score to repository.find results (#68894) (#69486)

* add `score` to repository.find results

* update generated doc

* fix FTR result set

* remove score from exports

* fix FTR for find API

* fix label

* fix tsdoc
This commit is contained in:
Pierre Gayvallet 2020-06-18 14:11:45 +02:00 committed by GitHub
parent bd4b72f376
commit 543319f492
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 123 additions and 23 deletions

View file

@ -157,6 +157,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
| [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry |
| [SavedObjectsFindOptions](./kibana-plugin-core-server.savedobjectsfindoptions.md) | |
| [SavedObjectsFindResponse](./kibana-plugin-core-server.savedobjectsfindresponse.md) | Return type of the Saved Objects <code>find()</code> method.<!-- -->\*Note\*: this type is different between the Public and Server Saved Objects clients. |
| [SavedObjectsFindResult](./kibana-plugin-core-server.savedobjectsfindresult.md) | |
| [SavedObjectsImportConflictError](./kibana-plugin-core-server.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. |
| [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) | Represents a failure to import. |
| [SavedObjectsImportMissingReferencesError](./kibana-plugin-core-server.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. |

View file

@ -20,6 +20,6 @@ export interface SavedObjectsFindResponse<T = unknown>
| --- | --- | --- |
| [page](./kibana-plugin-core-server.savedobjectsfindresponse.page.md) | <code>number</code> | |
| [per\_page](./kibana-plugin-core-server.savedobjectsfindresponse.per_page.md) | <code>number</code> | |
| [saved\_objects](./kibana-plugin-core-server.savedobjectsfindresponse.saved_objects.md) | <code>Array&lt;SavedObject&lt;T&gt;&gt;</code> | |
| [saved\_objects](./kibana-plugin-core-server.savedobjectsfindresponse.saved_objects.md) | <code>Array&lt;SavedObjectsFindResult&lt;T&gt;&gt;</code> | |
| [total](./kibana-plugin-core-server.savedobjectsfindresponse.total.md) | <code>number</code> | |

View file

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
saved_objects: Array<SavedObject<T>>;
saved_objects: Array<SavedObjectsFindResult<T>>;
```

View file

@ -0,0 +1,19 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsFindResult](./kibana-plugin-core-server.savedobjectsfindresult.md)
## SavedObjectsFindResult interface
<b>Signature:</b>
```typescript
export interface SavedObjectsFindResult<T = unknown> extends SavedObject<T>
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [score](./kibana-plugin-core-server.savedobjectsfindresult.score.md) | <code>number</code> | The Elasticsearch <code>_score</code> of this result. |

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-core-server](./kibana-plugin-core-server.md) &gt; [SavedObjectsFindResult](./kibana-plugin-core-server.savedobjectsfindresult.md) &gt; [score](./kibana-plugin-core-server.savedobjectsfindresult.score.md)
## SavedObjectsFindResult.score property
The Elasticsearch `_score` of this result.
<b>Signature:</b>
```typescript
score: number;
```

View file

@ -303,7 +303,6 @@ export class SavedObjectsClient {
query,
});
return request.then((resp) => {
resp.saved_objects = resp.saved_objects.map((d) => this.createSavedObject(d));
return renameKeys<
PromiseType<ReturnType<SavedObjectsApi['find']>>,
SavedObjectsFindResponsePublic
@ -314,7 +313,10 @@ export class SavedObjectsClient {
per_page: 'perPage',
page: 'page',
},
resp
{
...resp,
saved_objects: resp.saved_objects.map((d) => this.createSavedObject(d)),
}
) as SavedObjectsFindResponsePublic<T>;
});
};

View file

@ -217,6 +217,7 @@ export {
SavedObjectsErrorHelpers,
SavedObjectsExportOptions,
SavedObjectsExportResultDetails,
SavedObjectsFindResult,
SavedObjectsFindResponse,
SavedObjectsImportConflictError,
SavedObjectsImportError,

View file

@ -47,6 +47,7 @@ describe('getSortedObjectsForExport()', () => {
id: '2',
type: 'search',
attributes: {},
score: 1,
references: [
{
name: 'name',
@ -59,6 +60,7 @@ describe('getSortedObjectsForExport()', () => {
id: '1',
type: 'index-pattern',
attributes: {},
score: 1,
references: [],
},
],
@ -133,6 +135,7 @@ describe('getSortedObjectsForExport()', () => {
id: '2',
type: 'search',
attributes: {},
score: 1,
references: [
{
name: 'name',
@ -145,6 +148,7 @@ describe('getSortedObjectsForExport()', () => {
id: '1',
type: 'index-pattern',
attributes: {},
score: 1,
references: [],
},
],
@ -192,6 +196,7 @@ describe('getSortedObjectsForExport()', () => {
id: '2',
type: 'search',
attributes: {},
score: 1,
references: [
{
name: 'name',
@ -204,6 +209,7 @@ describe('getSortedObjectsForExport()', () => {
id: '1',
type: 'index-pattern',
attributes: {},
score: 1,
references: [],
},
],
@ -279,6 +285,7 @@ describe('getSortedObjectsForExport()', () => {
id: '2',
type: 'search',
attributes: {},
score: 1,
references: [
{
name: 'name',
@ -291,6 +298,7 @@ describe('getSortedObjectsForExport()', () => {
id: '1',
type: 'index-pattern',
attributes: {},
score: 1,
references: [],
},
],
@ -366,6 +374,7 @@ describe('getSortedObjectsForExport()', () => {
id: '2',
type: 'search',
attributes: {},
score: 1,
references: [
{
type: 'index-pattern',
@ -378,6 +387,7 @@ describe('getSortedObjectsForExport()', () => {
id: '1',
type: 'index-pattern',
attributes: {},
score: 1,
references: [],
},
],
@ -405,6 +415,7 @@ describe('getSortedObjectsForExport()', () => {
attributes: {
name: 'baz',
},
score: 1,
references: [],
},
{
@ -413,6 +424,7 @@ describe('getSortedObjectsForExport()', () => {
attributes: {
name: 'foo',
},
score: 1,
references: [],
},
{
@ -421,6 +433,7 @@ describe('getSortedObjectsForExport()', () => {
attributes: {
name: 'bar',
},
score: 1,
references: [],
},
],

View file

@ -116,8 +116,11 @@ async function fetchObjectsToExport({
}
// 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
return (
findResponse.saved_objects
// exclude the find-specific `score` property from the exported objects
.map(({ score, ...obj }) => obj)
.sort((a: SavedObject, b: SavedObject) => (a.id > b.id ? 1 : -1))
);
} else {
throw Boom.badRequest('Either `type` or `objects` are required.');

View file

@ -79,6 +79,7 @@ describe('GET /api/saved_objects/_find', () => {
timeFieldName: '@timestamp',
notExpandable: true,
attributes: {},
score: 1,
references: [],
},
{
@ -88,6 +89,7 @@ describe('GET /api/saved_objects/_find', () => {
timeFieldName: '@timestamp',
notExpandable: true,
attributes: {},
score: 1,
references: [],
},
],

View file

@ -1939,7 +1939,7 @@ describe('SavedObjectsRepository', () => {
{
_index: '.kibana',
_id: `${namespace ? `${namespace}:` : ''}config:6.0.0-alpha1`,
_score: 1,
_score: 2,
...mockVersionProps,
_source: {
namespace,
@ -1954,7 +1954,7 @@ describe('SavedObjectsRepository', () => {
{
_index: '.kibana',
_id: `${namespace ? `${namespace}:` : ''}index-pattern:stocks-*`,
_score: 1,
_score: 3,
...mockVersionProps,
_source: {
namespace,
@ -1970,7 +1970,7 @@ describe('SavedObjectsRepository', () => {
{
_index: '.kibana',
_id: `${NAMESPACE_AGNOSTIC_TYPE}:something`,
_score: 1,
_score: 4,
...mockVersionProps,
_source: {
type: NAMESPACE_AGNOSTIC_TYPE,
@ -2131,6 +2131,7 @@ describe('SavedObjectsRepository', () => {
type: doc._source.type,
...mockTimestampFields,
version: mockVersion,
score: doc._score,
attributes: doc._source[doc._source.type],
references: [],
});
@ -2153,6 +2154,7 @@ describe('SavedObjectsRepository', () => {
type: doc._source.type,
...mockTimestampFields,
version: mockVersion,
score: doc._score,
attributes: doc._source[doc._source.type],
references: [],
});

View file

@ -40,6 +40,7 @@ import {
SavedObjectsBulkUpdateResponse,
SavedObjectsCreateOptions,
SavedObjectsFindResponse,
SavedObjectsFindResult,
SavedObjectsUpdateOptions,
SavedObjectsUpdateResponse,
SavedObjectsBulkUpdateObject,
@ -673,8 +674,11 @@ export class SavedObjectsRepository {
page,
per_page: perPage,
total: response.hits.total,
saved_objects: response.hits.hits.map((hit: SavedObjectsRawDoc) =>
this._rawToSavedObject(hit)
saved_objects: response.hits.hits.map(
(hit: SavedObjectsRawDoc): SavedObjectsFindResult => ({
...this._rawToSavedObject(hit),
score: (hit as any)._score,
})
),
};
}

View file

@ -79,6 +79,17 @@ export interface SavedObjectsBulkResponse<T = unknown> {
saved_objects: Array<SavedObject<T>>;
}
/**
*
* @public
*/
export interface SavedObjectsFindResult<T = unknown> extends SavedObject<T> {
/**
* The Elasticsearch `_score` of this result.
*/
score: number;
}
/**
* Return type of the Saved Objects `find()` method.
*
@ -88,7 +99,7 @@ export interface SavedObjectsBulkResponse<T = unknown> {
* @public
*/
export interface SavedObjectsFindResponse<T = unknown> {
saved_objects: Array<SavedObject<T>>;
saved_objects: Array<SavedObjectsFindResult<T>>;
total: number;
per_page: number;
page: number;

View file

@ -2039,11 +2039,16 @@ export interface SavedObjectsFindResponse<T = unknown> {
// (undocumented)
per_page: number;
// (undocumented)
saved_objects: Array<SavedObject<T>>;
saved_objects: Array<SavedObjectsFindResult<T>>;
// (undocumented)
total: number;
}
// @public (undocumented)
export interface SavedObjectsFindResult<T = unknown> extends SavedObject<T> {
score: number;
}
// @public
export interface SavedObjectsImportConflictError {
// (undocumented)

View file

@ -18,17 +18,18 @@
*/
import { times } from 'lodash';
import { SavedObjectsFindOptions, SavedObject } from 'src/core/server';
import { SavedObjectsFindOptions, SavedObjectsFindResult } from 'src/core/server';
import { savedObjectsClientMock } from '../../../../core/server/mocks';
import { findAll } from './find_all';
describe('findAll', () => {
let savedObjectsClient: ReturnType<typeof savedObjectsClientMock.create>;
const createObj = (id: number): SavedObject => ({
const createObj = (id: number): SavedObjectsFindResult => ({
type: 'type',
id: `id-${id}`,
attributes: {},
score: 1,
references: [],
});

View file

@ -77,6 +77,7 @@ describe('findRelationships', () => {
type: 'parent-type',
id: 'parent-id',
attributes: {},
score: 1,
references: [],
},
],

View file

@ -46,6 +46,7 @@ export default function ({ getService }) {
attributes: {
title: 'Count of requests',
},
score: 0,
migrationVersion: resp.body.saved_objects[0].migrationVersion,
references: [
{
@ -134,6 +135,7 @@ export default function ({ getService }) {
.searchSourceJSON,
},
},
score: 0,
references: [
{
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',

View file

@ -56,6 +56,7 @@ export default function ({ getService }: FtrProviderContext) {
type: 'index-pattern',
},
],
score: 0,
updated_at: '2017-09-21T18:51:23.794Z',
meta: {
editUrl:

View file

@ -386,6 +386,7 @@ describe('getAll()', () => {
foo: 'bar',
},
},
score: 1,
references: [],
},
],

View file

@ -1667,6 +1667,7 @@ describe('find()', () => {
},
],
},
score: 1,
references: [
{
name: 'action_0',

View file

@ -222,7 +222,12 @@ describe('Utils', () => {
];
const res = transformCases(
{ saved_objects: mockCases, total: mockCases.length, per_page: 10, page: 1 },
{
saved_objects: mockCases.map((obj) => ({ ...obj, score: 1 })),
total: mockCases.length,
per_page: 10,
page: 1,
},
2,
2,
extraCaseData,
@ -232,7 +237,11 @@ describe('Utils', () => {
page: 1,
per_page: 10,
total: mockCases.length,
cases: flattenCaseSavedObjects(mockCases, extraCaseData, '123'),
cases: flattenCaseSavedObjects(
mockCases.map((obj) => ({ ...obj, score: 1 })),
extraCaseData,
'123'
),
count_open_cases: 2,
count_closed_cases: 2,
});
@ -500,7 +509,7 @@ describe('Utils', () => {
describe('transformComments', () => {
it('transforms correctly', () => {
const comments = {
saved_objects: mockCaseComments,
saved_objects: mockCaseComments.map((obj) => ({ ...obj, score: 1 })),
total: mockCaseComments.length,
per_page: 10,
page: 1,

View file

@ -101,7 +101,7 @@ export const transformCases = (
});
export const flattenCaseSavedObjects = (
savedObjects: SavedObjectsFindResponse<CaseAttributes>['saved_objects'],
savedObjects: Array<SavedObject<CaseAttributes>>,
totalCommentByCase: TotalCommentByCase[],
caseConfigureConnectorId: string = 'none'
): CaseResponse[] =>
@ -146,7 +146,7 @@ export const transformComments = (
});
export const flattenCommentSavedObjects = (
savedObjects: SavedObjectsFindResponse<CommentAttributes>['saved_objects']
savedObjects: Array<SavedObject<CommentAttributes>>
): CommentResponse[] =>
savedObjects.reduce((acc: CommentResponse[], savedObject: SavedObject<CommentAttributes>) => {
return [...acc, flattenCommentSavedObject(savedObject)];

View file

@ -676,12 +676,14 @@ describe('#find', () => {
id: 'some-id',
type: 'unknown-type',
attributes: { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' },
score: 1,
references: [],
},
{
id: 'some-id-2',
type: 'unknown-type',
attributes: { attrOne: 'one', attrSecret: 'secret', attrThree: 'three' },
score: 1,
references: [],
},
],
@ -722,6 +724,7 @@ describe('#find', () => {
attrNotSoSecret: 'not-so-secret',
attrThree: 'three',
},
score: 1,
references: [],
},
{
@ -733,6 +736,7 @@ describe('#find', () => {
attrNotSoSecret: '*not-so-secret*',
attrThree: 'three',
},
score: 1,
references: [],
},
],
@ -793,6 +797,7 @@ describe('#find', () => {
attrNotSoSecret: 'not-so-secret',
attrThree: 'three',
},
score: 1,
references: [],
},
{
@ -804,6 +809,7 @@ describe('#find', () => {
attrNotSoSecret: '*not-so-secret*',
attrThree: 'three',
},
score: 1,
references: [],
},
],

View file

@ -549,6 +549,7 @@ export const getFindResultStatus = (): SavedObjectsFindResponse<
searchAfterTimeDurations: ['200.00'],
bulkCreateTimeDurations: ['800.43'],
},
score: 1,
references: [],
updated_at: '2020-02-18T15:26:51.333Z',
version: 'WzQ2LDFd',
@ -570,6 +571,7 @@ export const getFindResultStatus = (): SavedObjectsFindResponse<
searchAfterTimeDurations: ['200.00'],
bulkCreateTimeDurations: ['800.43'],
},
score: 1,
references: [],
updated_at: '2020-02-18T15:15:58.860Z',
version: 'WzMyLDFd',

View file

@ -391,7 +391,7 @@ export const exampleFindRuleStatusResponse: (
total: 1,
per_page: 6,
page: 1,
saved_objects: mockStatuses,
saved_objects: mockStatuses.map((obj) => ({ ...obj, score: 1 })),
});
export const mockLogger: Logger = loggingServiceMock.createLogger();

View file

@ -138,7 +138,7 @@ const ERROR_NAMESPACE_SPECIFIED = 'Spaces currently determines the namespaces';
test(`passes options.type to baseClient if valid singular type specified`, async () => {
const { client, baseClient } = await createSpacesSavedObjectsClient();
const expectedReturnValue = {
saved_objects: [createMockResponse()],
saved_objects: [createMockResponse()].map((obj) => ({ ...obj, score: 1 })),
total: 1,
per_page: 0,
page: 0,
@ -158,7 +158,7 @@ const ERROR_NAMESPACE_SPECIFIED = 'Spaces currently determines the namespaces';
test(`supplements options with the current namespace`, async () => {
const { client, baseClient } = await createSpacesSavedObjectsClient();
const expectedReturnValue = {
saved_objects: [createMockResponse()],
saved_objects: [createMockResponse()].map((obj) => ({ ...obj, score: 1 })),
total: 1,
per_page: 0,
page: 0,