Skip to content

Commit

Permalink
Merge branch 'main' into feature/140829
Browse files Browse the repository at this point in the history
  • Loading branch information
flash1293 authored Oct 4, 2022
2 parents f9b6a97 + 53bf927 commit 5be30d0
Show file tree
Hide file tree
Showing 137 changed files with 2,945 additions and 1,415 deletions.
9 changes: 9 additions & 0 deletions docs/api/saved-objects/find.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ experimental[] Retrieve a paginated set of {kib} saved objects by various condit
`has_reference`::
(Optional, object) Filters to objects that have a relationship with the type and ID combination.

`has_reference_operator`::
(Optional, string) The operator to use for the `has_reference` parameter. Either `OR` or `AND`. Defaults to `OR`.

`has_no_reference`::
(Optional, object) Filters to objects that do not have a relationship with the type and ID combination.

`has_no_reference_operator`::
(Optional, string) The operator to use for the `has_no_reference` parameter. Either `OR` or `AND`. Defaults to `OR`.

`filter`::
(Optional, string) The filter is a KQL string with the caveat that if you filter with an attribute from your saved object type,
it should look like that: `savedObjectType.attributes.title: "myTitle"`. However, If you use a root attribute of a saved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4182,6 +4182,10 @@ describe('SavedObjectsRepository', () => {
type: 'foo',
id: '1',
},
hasNoReference: {
type: 'bar',
id: '1',
},
};

it(`passes mappings, registry, and search options to getSearchDsl`, async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,8 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
rootSearchFields,
hasReference,
hasReferenceOperator,
hasNoReference,
hasNoReferenceOperator,
page = FIND_DEFAULT_PAGE,
perPage = FIND_DEFAULT_PER_PAGE,
pit,
Expand Down Expand Up @@ -1235,6 +1237,8 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
typeToNamespacesMap,
hasReference,
hasReferenceOperator,
hasNoReference,
hasNoReferenceOperator,
kueryNode,
}),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,17 +195,18 @@ describe('#getQueryParams', () => {
});
});

describe('reference filter clause', () => {
describe('`hasReference` parameter', () => {
it('does not call `getReferencesFilter` when `hasReference` is not specified', () => {
getQueryParams({
registry,
hasReference: undefined,
});

expect(getReferencesFilterMock).not.toHaveBeenCalled();
describe('reference/noreference filter clause', () => {
it('does not call `getReferencesFilter` when neither `hasReference` nor `hasNoReference` are specified', () => {
getQueryParams({
registry,
hasReference: undefined,
hasNoReference: undefined,
});

expect(getReferencesFilterMock).not.toHaveBeenCalled();
});

describe('`hasReference` parameter', () => {
it('calls `getReferencesFilter` with the correct parameters', () => {
const hasReference = { id: 'foo', type: 'bar' };
getQueryParams({
Expand Down Expand Up @@ -235,6 +236,38 @@ describe('#getQueryParams', () => {
expect(filters.some((filter) => filter.references_filter === true)).toBeDefined();
});
});

describe('`hasNoReference` parameter', () => {
it('calls `getReferencesFilter` with the correct parameters', () => {
const hasNoReference = { id: 'noFoo', type: 'bar' };
getQueryParams({
registry,
hasNoReference,
hasNoReferenceOperator: 'AND',
});

expect(getReferencesFilterMock).toHaveBeenCalledTimes(1);
expect(getReferencesFilterMock).toHaveBeenCalledWith({
must: false,
references: [hasNoReference],
operator: 'AND',
});
});

it('includes the return of `getReferencesFilter` in the `filter` clause', () => {
getReferencesFilterMock.mockReturnValue({ references_filter: true });

const hasNoReference = { id: 'noFoo', type: 'bar' };
const result = getQueryParams({
registry,
hasNoReference,
hasReferenceOperator: 'AND',
});

const filters: any[] = result.query.bool.filter;
expect(filters.some((filter) => filter.references_filter === true)).toBeDefined();
});
});
});

describe('type filter clauses', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import * as esKuery from '@kbn/es-query';
import type { SavedObjectTypeIdTuple } from '@kbn/core-saved-objects-common';

type KueryNode = any;

Expand Down Expand Up @@ -123,11 +124,6 @@ function getClauseForType(
};
}

export interface HasReferenceQueryParams {
type: string;
id: string;
}

export type SearchOperator = 'AND' | 'OR';

interface QueryParams {
Expand All @@ -139,15 +135,24 @@ interface QueryParams {
defaultSearchOperator?: SearchOperator;
searchFields?: string[];
rootSearchFields?: string[];
hasReference?: HasReferenceQueryParams | HasReferenceQueryParams[];
hasReference?: SavedObjectTypeIdTuple | SavedObjectTypeIdTuple[];
hasReferenceOperator?: SearchOperator;
hasNoReference?: SavedObjectTypeIdTuple | SavedObjectTypeIdTuple[];
hasNoReferenceOperator?: SearchOperator;
kueryNode?: KueryNode;
}

// A de-duplicated set of namespaces makes for a more efficient query.
const uniqNamespaces = (namespacesToNormalize?: string[]) =>
namespacesToNormalize ? Array.from(new Set(namespacesToNormalize)) : undefined;

const toArray = (val: unknown) => {
if (typeof val === 'undefined') {
return val;
}
return !Array.isArray(val) ? [val] : val;
};

/**
* Get the "query" related keys for the search body
*/
Expand All @@ -162,16 +167,17 @@ export function getQueryParams({
defaultSearchOperator,
hasReference,
hasReferenceOperator,
hasNoReference,
hasNoReferenceOperator,
kueryNode,
}: QueryParams) {
const types = getTypes(
registry,
typeToNamespacesMap ? Array.from(typeToNamespacesMap.keys()) : type
);

if (hasReference && !Array.isArray(hasReference)) {
hasReference = [hasReference];
}
hasReference = toArray(hasReference);
hasNoReference = toArray(hasNoReference);

const bool: any = {
filter: [
Expand All @@ -184,6 +190,15 @@ export function getQueryParams({
}),
]
: []),
...(hasNoReference?.length
? [
getReferencesFilter({
references: hasNoReference,
operator: hasNoReferenceOperator,
must: false,
}),
]
: []),
{
bool: {
should: types.map((shouldType) => {
Expand Down
Loading

0 comments on commit 5be30d0

Please sign in to comment.