mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Allow passing a default operator to use on saved object client find operations (#29339)
* Allow passing a default operator to use on find operations * Default operator to OR like elasticsearch to avoid passing null * Add dashboard search tests * Make search_operator optional * Fix query_params.test.js * Include searchOperator in saved_object_finder * Apply PR feedback * Rename searchOperator to defaultSearchOperator
This commit is contained in:
parent
9ca8c9fe67
commit
9eef63f783
15 changed files with 99 additions and 12 deletions
|
@ -21,6 +21,8 @@ Note: You cannot access this endpoint via the Console in Kibana.
|
|||
(number) The page of objects to return
|
||||
`search` (optional)::
|
||||
(string) A {ref}/query-dsl-simple-query-string-query.html[simple_query_string] Elasticsearch query to filter the objects in the response
|
||||
`default_search_operator` (optional)::
|
||||
(string) The default operator to use for the `simple_query_string`
|
||||
`search_fields` (optional)::
|
||||
(array|string) The fields to perform the `simple_query_string` parsed query against
|
||||
`fields` (optional)::
|
||||
|
|
|
@ -31,6 +31,7 @@ export const createFindRoute = (prereqs) => ({
|
|||
page: Joi.number().min(0).default(1),
|
||||
type: Joi.array().items(Joi.string()).single().required(),
|
||||
search: Joi.string().allow('').optional(),
|
||||
default_search_operator: Joi.string().valid('OR', 'AND').default('OR'),
|
||||
search_fields: Joi.array().items(Joi.string()).single(),
|
||||
sort_field: Joi.array().items(Joi.string()).single(),
|
||||
fields: Joi.array().items(Joi.string()).single()
|
||||
|
|
|
@ -105,7 +105,7 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
expect(savedObjectsClient.find.calledOnce).toBe(true);
|
||||
|
||||
const options = savedObjectsClient.find.getCall(0).args[0];
|
||||
expect(options).toEqual({ perPage: 20, page: 1, type: ['foo', 'bar'] });
|
||||
expect(options).toEqual({ perPage: 20, page: 1, type: ['foo', 'bar'], defaultSearchOperator: 'OR' });
|
||||
});
|
||||
|
||||
it('accepts the query parameter page/per_page', async () => {
|
||||
|
@ -119,7 +119,7 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
expect(savedObjectsClient.find.calledOnce).toBe(true);
|
||||
|
||||
const options = savedObjectsClient.find.getCall(0).args[0];
|
||||
expect(options).toEqual({ perPage: 10, page: 50, type: ['foo'] });
|
||||
expect(options).toEqual({ perPage: 10, page: 50, type: ['foo'], defaultSearchOperator: 'OR' });
|
||||
});
|
||||
|
||||
it('accepts the query parameter search_fields', async () => {
|
||||
|
@ -133,7 +133,7 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
expect(savedObjectsClient.find.calledOnce).toBe(true);
|
||||
|
||||
const options = savedObjectsClient.find.getCall(0).args[0];
|
||||
expect(options).toEqual({ perPage: 20, page: 1, searchFields: ['title'], type: ['foo'] });
|
||||
expect(options).toEqual({ perPage: 20, page: 1, searchFields: ['title'], type: ['foo'], defaultSearchOperator: 'OR' });
|
||||
});
|
||||
|
||||
it('accepts the query parameter fields as a string', async () => {
|
||||
|
@ -147,7 +147,7 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
expect(savedObjectsClient.find.calledOnce).toBe(true);
|
||||
|
||||
const options = savedObjectsClient.find.getCall(0).args[0];
|
||||
expect(options).toEqual({ perPage: 20, page: 1, fields: ['title'], type: ['foo'] });
|
||||
expect(options).toEqual({ perPage: 20, page: 1, fields: ['title'], type: ['foo'], defaultSearchOperator: 'OR' });
|
||||
});
|
||||
|
||||
it('accepts the query parameter fields as an array', async () => {
|
||||
|
@ -162,7 +162,7 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
|
||||
const options = savedObjectsClient.find.getCall(0).args[0];
|
||||
expect(options).toEqual({
|
||||
perPage: 20, page: 1, fields: ['title', 'description'], type: ['foo']
|
||||
perPage: 20, page: 1, fields: ['title', 'description'], type: ['foo'], defaultSearchOperator: 'OR'
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -177,7 +177,7 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
expect(savedObjectsClient.find.calledOnce).toBe(true);
|
||||
|
||||
const options = savedObjectsClient.find.getCall(0).args[0];
|
||||
expect(options).toEqual({ perPage: 20, page: 1, type: ['index-pattern'] });
|
||||
expect(options).toEqual({ perPage: 20, page: 1, type: ['index-pattern'], defaultSearchOperator: 'OR' });
|
||||
});
|
||||
|
||||
it('accepts the query parameter type as an array', async () => {
|
||||
|
@ -191,6 +191,6 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
expect(savedObjectsClient.find.calledOnce).toBe(true);
|
||||
|
||||
const options = savedObjectsClient.find.getCall(0).args[0];
|
||||
expect(options).toEqual({ perPage: 20, page: 1, type: ['index-pattern', 'visualization'] });
|
||||
expect(options).toEqual({ perPage: 20, page: 1, type: ['index-pattern', 'visualization'], defaultSearchOperator: 'OR' });
|
||||
});
|
||||
});
|
||||
|
|
|
@ -283,6 +283,7 @@ export class SavedObjectsRepository {
|
|||
* @param {object} [options={}]
|
||||
* @property {(string|Array<string>)} [options.type]
|
||||
* @property {string} [options.search]
|
||||
* @property {string} [options.defaultSearchOperator]
|
||||
* @property {Array<string>} [options.searchFields] - see Elasticsearch Simple Query String
|
||||
* Query field argument for more information
|
||||
* @property {integer} [options.page=1]
|
||||
|
@ -297,6 +298,7 @@ export class SavedObjectsRepository {
|
|||
const {
|
||||
type,
|
||||
search,
|
||||
defaultSearchOperator = 'OR',
|
||||
searchFields,
|
||||
page = 1,
|
||||
perPage = 20,
|
||||
|
@ -329,6 +331,7 @@ export class SavedObjectsRepository {
|
|||
version: true,
|
||||
...getSearchDsl(this._mappings, this._schema, {
|
||||
search,
|
||||
defaultSearchOperator,
|
||||
searchFields,
|
||||
type,
|
||||
sortField,
|
||||
|
|
|
@ -812,7 +812,7 @@ describe('SavedObjectsRepository', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('passes mappings, schema, search, searchFields, type, sortField, and sortOrder to getSearchDsl', async () => {
|
||||
it('passes mappings, schema, search, defaultSearchOperator, searchFields, type, sortField, and sortOrder to getSearchDsl', async () => {
|
||||
callAdminCluster.returns(namespacedSearchResults);
|
||||
const relevantOpts = {
|
||||
namespace: 'foo-namespace',
|
||||
|
@ -821,6 +821,7 @@ describe('SavedObjectsRepository', () => {
|
|||
type: 'bar',
|
||||
sortField: 'name',
|
||||
sortOrder: 'desc',
|
||||
defaultSearchOperator: 'AND',
|
||||
};
|
||||
|
||||
await savedObjectsRepository.find(relevantOpts);
|
||||
|
|
|
@ -98,9 +98,10 @@ function getClauseForType(schema, namespace, type) {
|
|||
* @param {(string|Array<string>)} type
|
||||
* @param {String} search
|
||||
* @param {Array<string>} searchFields
|
||||
* @param {String} defaultSearchOperator
|
||||
* @return {Object}
|
||||
*/
|
||||
export function getQueryParams(mappings, schema, namespace, type, search, searchFields) {
|
||||
export function getQueryParams(mappings, schema, namespace, type, search, searchFields, defaultSearchOperator) {
|
||||
const types = getTypes(mappings, type);
|
||||
const bool = {
|
||||
filter: [{
|
||||
|
@ -119,7 +120,8 @@ export function getQueryParams(mappings, schema, namespace, type, search, search
|
|||
...getFieldsForTypes(
|
||||
searchFields,
|
||||
types
|
||||
)
|
||||
),
|
||||
...(defaultSearchOperator ? { default_operator: defaultSearchOperator } : {}),
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
|
@ -714,4 +714,68 @@ describe('searchDsl/queryParams', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('type (plural, namespaced and global), search, defaultSearchOperator', () => {
|
||||
it('supports defaultSearchOperator', () => {
|
||||
expect(getQueryParams(MAPPINGS, SCHEMA, 'foo-namespace', ['saved', 'global'], 'foo', null, 'AND'))
|
||||
.toEqual({
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
bool: {
|
||||
minimum_should_match: 1,
|
||||
should: [
|
||||
{
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
term: {
|
||||
type: 'saved',
|
||||
},
|
||||
},
|
||||
{
|
||||
term: {
|
||||
namespace: 'foo-namespace',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
term: {
|
||||
type: 'global',
|
||||
},
|
||||
},
|
||||
],
|
||||
must_not: [
|
||||
{
|
||||
exists: {
|
||||
field: 'namespace',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
must: [
|
||||
{
|
||||
simple_query_string: {
|
||||
all_fields: true,
|
||||
default_operator: 'AND',
|
||||
query: 'foo',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@ export function getSearchDsl(mappings, schema, options = {}) {
|
|||
const {
|
||||
type,
|
||||
search,
|
||||
defaultSearchOperator,
|
||||
searchFields,
|
||||
sortField,
|
||||
sortOrder,
|
||||
|
@ -41,7 +42,7 @@ export function getSearchDsl(mappings, schema, options = {}) {
|
|||
}
|
||||
|
||||
return {
|
||||
...getQueryParams(mappings, schema, namespace, type, search, searchFields),
|
||||
...getQueryParams(mappings, schema, namespace, type, search, searchFields, defaultSearchOperator),
|
||||
...getSortingParams(mappings, type, sortField, sortOrder),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ describe('getSearchDsl', () => {
|
|||
type: 'foo',
|
||||
search: 'bar',
|
||||
searchFields: ['baz'],
|
||||
defaultSearchOperator: 'AND',
|
||||
};
|
||||
|
||||
getSearchDsl(mappings, schema, opts);
|
||||
|
@ -67,6 +68,7 @@ describe('getSearchDsl', () => {
|
|||
opts.type,
|
||||
opts.search,
|
||||
opts.searchFields,
|
||||
opts.defaultSearchOperator,
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -139,6 +139,7 @@ export class SavedObjectsClient {
|
|||
* @param {object} [options={}]
|
||||
* @property {(string|Array<string>)} [options.type]
|
||||
* @property {string} [options.search]
|
||||
* @property {string} [options.defaultSearchOperator]
|
||||
* @property {Array<string>} [options.searchFields] - see Elasticsearch Simple Query String
|
||||
* Query field argument for more information
|
||||
* @property {integer} [options.page=1]
|
||||
|
|
|
@ -118,6 +118,7 @@ export class SavedObjectLoader {
|
|||
perPage: size,
|
||||
page: 1,
|
||||
searchFields: ['title^3', 'description'],
|
||||
defaultSearchOperator: 'AND',
|
||||
fields,
|
||||
}).then((resp) => {
|
||||
return {
|
||||
|
|
|
@ -113,7 +113,8 @@ class SavedObjectFinderUI extends React.Component {
|
|||
search: filter ? `${filter}*` : undefined,
|
||||
page: 1,
|
||||
perPage: chrome.getUiSettingsClient().get('savedObjects:listingLimit'),
|
||||
searchFields: ['title^3', 'description']
|
||||
searchFields: ['title^3', 'description'],
|
||||
defaultSearchOperator: 'AND',
|
||||
});
|
||||
|
||||
if (this.props.savedObjectType === 'visualization'
|
||||
|
|
|
@ -111,6 +111,7 @@ export class SavedObjectsClient {
|
|||
* @param {object} [options={}]
|
||||
* @property {string} options.type
|
||||
* @property {string} options.search
|
||||
* @property {string} options.defaultSearchOperator
|
||||
* @property {string} options.searchFields - see Elasticsearch Simple Query String
|
||||
* Query field argument for more information
|
||||
* @property {integer} [options.page=1]
|
||||
|
|
|
@ -122,6 +122,12 @@ export default function ({ getService, getPageObjects }) {
|
|||
const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable();
|
||||
expect(countOfDashboards).to.equal(1);
|
||||
});
|
||||
|
||||
it('is using AND operator', async function () {
|
||||
await PageObjects.dashboard.searchForDashboardWithName('three words');
|
||||
const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable();
|
||||
expect(countOfDashboards).to.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('search by title', function () {
|
||||
|
|
|
@ -140,6 +140,7 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient {
|
|||
* @param {object} [options={}]
|
||||
* @property {(string|Array<string>)} [options.type]
|
||||
* @property {string} [options.search]
|
||||
* @property {string} [options.defaultSearchOperator]
|
||||
* @property {Array<string>} [options.searchFields] - see Elasticsearch Simple Query String
|
||||
* Query field argument for more information
|
||||
* @property {integer} [options.page=1]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue