Default search params for ignore_unavailable and rest_total_hits_as_int (#50953)

* Default search params for ignore_unavailable and rest_total_hits_as_int

* Update code with options arg

* Fix filter matches index for filters with partial meta

* Fix tests
This commit is contained in:
Lukas Olson 2019-11-25 20:58:35 -07:00 committed by GitHub
parent d158fd8881
commit 320fa5a550
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 51 additions and 40 deletions

View file

@ -49,11 +49,11 @@ export interface IResponseTypesMap {
export type ISearchGeneric = <T extends TStrategyTypes = typeof DEFAULT_SEARCH_STRATEGY>(
request: IRequestTypesMap[T],
options: ISearchOptions,
options?: ISearchOptions,
strategy?: T
) => Observable<IResponseTypesMap[T]>;
export type ISearch<T extends TStrategyTypes = typeof DEFAULT_SEARCH_STRATEGY> = (
request: IRequestTypesMap[T],
options: ISearchOptions
options?: ISearchOptions
) => Observable<IResponseTypesMap[T]>;

View file

@ -34,7 +34,7 @@ export const syncSearchStrategyProvider: TSearchStrategyProvider<typeof SYNC_SEA
) => {
const search: ISearch<typeof SYNC_SEARCH_STRATEGY> = (
request: ISyncSearchRequest,
options: ISearchOptions
options: ISearchOptions = {}
) => {
const response: Promise<IKibanaSearchResponse> = context.core.http.fetch(
`/internal/search/${request.serverStrategy}`,

View file

@ -55,7 +55,7 @@ describe('createApi', () => {
});
it('should throw if no provider is found for the given name', () => {
expect(api.search({}, 'noneByThisName')).rejects.toThrowErrorMatchingInlineSnapshot(
expect(api.search({}, {}, 'noneByThisName')).rejects.toThrowErrorMatchingInlineSnapshot(
`"No strategy found for noneByThisName"`
);
});

View file

@ -30,7 +30,7 @@ export function createApi({
caller: APICaller;
}) {
const api: IRouteHandlerSearchContext = {
search: async (request, strategyName) => {
search: async (request, options, strategyName) => {
const name = strategyName ? strategyName : DEFAULT_SEARCH_STRATEGY;
const strategyProvider = searchStrategies[name];
if (!strategyProvider) {

View file

@ -66,7 +66,7 @@ describe('ES search strategy', () => {
expect(spy).toBeCalled();
});
it('calls the API caller with the params', () => {
it('calls the API caller with the params with defaults', () => {
const params = { index: 'logstash-*' };
const esSearch = esSearchStrategyProvider(
{
@ -80,7 +80,31 @@ describe('ES search strategy', () => {
expect(mockApiCaller).toBeCalled();
expect(mockApiCaller.mock.calls[0][0]).toBe('search');
expect(mockApiCaller.mock.calls[0][1]).toEqual(params);
expect(mockApiCaller.mock.calls[0][1]).toEqual({
...params,
ignoreUnavailable: true,
restTotalHitsAsInt: true,
});
});
it('calls the API caller with overridden defaults', () => {
const params = { index: 'logstash-*', ignoreUnavailable: false };
const esSearch = esSearchStrategyProvider(
{
core: mockCoreSetup,
},
mockApiCaller,
mockSearch
);
esSearch.search({ params });
expect(mockApiCaller).toBeCalled();
expect(mockApiCaller.mock.calls[0][0]).toBe('search');
expect(mockApiCaller.mock.calls[0][1]).toEqual({
...params,
restTotalHitsAsInt: true,
});
});
it('returns total, loaded, and raw response', async () => {

View file

@ -18,7 +18,7 @@
*/
import { APICaller } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import { IEsSearchRequest, ES_SEARCH_STRATEGY } from '../../../common/search';
import { ES_SEARCH_STRATEGY } from '../../../common/search';
import { ISearchStrategy, TSearchStrategyProvider } from '../i_search_strategy';
import { ISearchContext } from '..';
@ -27,16 +27,17 @@ export const esSearchStrategyProvider: TSearchStrategyProvider<typeof ES_SEARCH_
caller: APICaller
): ISearchStrategy<typeof ES_SEARCH_STRATEGY> => {
return {
search: async (request: IEsSearchRequest) => {
search: async (request, options) => {
const params = {
ignoreUnavailable: true, // Don't fail if the index/indices don't exist
restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range
...request.params,
};
if (request.debug) {
// eslint-disable-next-line
console.log(JSON.stringify(request, null, 2));
console.log(JSON.stringify(params, null, 2));
}
const esSearchResponse = (await caller('search', {
...request.params,
// TODO: could do something like this here?
// ...getCurrentSearchParams(context),
})) as SearchResponse<any>;
const esSearchResponse = (await caller('search', params, options)) as SearchResponse<any>;
// The above query will either complete or timeout and throw an error.
// There is no progress indication on this api.

View file

@ -22,6 +22,10 @@ import { TStrategyTypes } from './strategy_types';
import { ES_SEARCH_STRATEGY, IEsSearchResponse } from '../../common/search/es_search';
import { IEsSearchRequest } from './es_search';
export interface ISearchOptions {
signal?: AbortSignal;
}
export interface IRequestTypesMap {
[ES_SEARCH_STRATEGY]: IEsSearchRequest;
[key: string]: IKibanaSearchRequest;
@ -34,9 +38,11 @@ export interface IResponseTypesMap {
export type ISearchGeneric = <T extends TStrategyTypes = typeof ES_SEARCH_STRATEGY>(
request: IRequestTypesMap[T],
options?: ISearchOptions,
strategy?: T
) => Promise<IResponseTypesMap[T]>;
export type ISearch<T extends TStrategyTypes> = (
request: IRequestTypesMap[T]
request: IRequestTypesMap[T],
options?: ISearchOptions
) => Promise<IResponseTypesMap[T]>;

View file

@ -60,7 +60,7 @@ describe('Search service', () => {
expect(mockSearch).toBeCalled();
expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody);
expect(mockSearch.mock.calls[0][1]).toBe(mockParams.strategy);
expect(mockSearch.mock.calls[0][2]).toBe(mockParams.strategy);
expect(mockResponse.ok).toBeCalled();
expect(mockResponse.ok.mock.calls[0][0]).toEqual({ body: 'yay' });
});
@ -92,7 +92,7 @@ describe('Search service', () => {
expect(mockSearch).toBeCalled();
expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody);
expect(mockSearch.mock.calls[0][1]).toBe(mockParams.strategy);
expect(mockSearch.mock.calls[0][2]).toBe(mockParams.strategy);
expect(mockResponse.internalError).toBeCalled();
expect(mockResponse.internalError.mock.calls[0][0]).toEqual({ body: 'oh no' });
});

View file

@ -36,7 +36,7 @@ export function registerSearchRoute(router: IRouter): void {
const searchRequest = request.body;
const strategy = request.params.strategy;
try {
const response = await context.search!.search(searchRequest, strategy);
const response = await context.search!.search(searchRequest, {}, strategy);
return res.ok({ body: response });
} catch (err) {
return res.internalError({ body: err });

View file

@ -77,7 +77,7 @@ export class SearchService implements Plugin<ISearchSetup, void> {
caller,
searchStrategies: this.searchStrategies,
});
return searchAPI.search(request, strategyName);
return searchAPI.search(request, {}, strategyName);
},
},
};

View file

@ -1,20 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export const FAKE_PROGRESS_STRATEGY = 'FAKE_PROGRESS_STRATEGY';