[ES|QL] More run query helpers (#183906)

## Summary

Part of https://github.com/elastic/kibana/issues/179641

Adds another run query helper based on the search strategy in our
esql-utils package.
This commit is contained in:
Stratoula Kalafateli 2024-05-23 23:09:27 +02:00 committed by GitHub
parent 66182b451b
commit 96b195b76c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 89 additions and 72 deletions

View file

@ -18,6 +18,7 @@ export {
appendWhereClauseToESQLQuery,
getESQLQueryColumns,
getESQLQueryColumnsRaw,
getESQLResults,
TextBasedLanguages,
} from './src';

View file

@ -16,4 +16,4 @@ export {
removeDropCommandsFromESQLQuery,
} from './utils/query_parsing_helpers';
export { appendToESQLQuery, appendWhereClauseToESQLQuery } from './utils/append_to_query';
export { getESQLQueryColumns, getESQLQueryColumnsRaw } from './utils/run_query';
export { getESQLQueryColumns, getESQLQueryColumnsRaw, getESQLResults } from './utils/run_query';

View file

@ -9,58 +9,23 @@ import { i18n } from '@kbn/i18n';
import type { DatatableColumn } from '@kbn/expressions-plugin/common';
import type { ISearchGeneric } from '@kbn/search-types';
import { esFieldTypeToKibanaFieldType } from '@kbn/field-types';
import type { ESQLColumn, ESQLSearchReponse } from '@kbn/es-types';
import type { ESQLColumn, ESQLSearchReponse, ESQLSearchParams } from '@kbn/es-types';
import { lastValueFrom } from 'rxjs';
import { ESQL_LATEST_VERSION } from '../../constants';
export async function getESQLQueryColumns({
esqlQuery,
search,
signal,
}: {
esqlQuery: string;
search: ISearchGeneric;
signal?: AbortSignal;
}): Promise<DatatableColumn[]> {
try {
const response = await lastValueFrom(
search(
{
params: {
query: `${esqlQuery} | limit 0`,
version: ESQL_LATEST_VERSION,
},
},
{
abortSignal: signal,
strategy: 'esql_async',
}
)
);
const columns =
(response.rawResponse as unknown as ESQLSearchReponse).columns?.map(({ name, type }) => {
const kibanaType = esFieldTypeToKibanaFieldType(type);
const column = {
id: name,
name,
meta: { type: kibanaType, esType: type },
} as DatatableColumn;
return column;
}) ?? [];
return columns;
} catch (error) {
throw new Error(
i18n.translate('esqlUtils.columnsErrorMsg', {
defaultMessage: 'Unable to load columns. {errorMessage}',
values: { errorMessage: error.message },
})
);
}
export function formatESQLColumns(columns: ESQLColumn[]): DatatableColumn[] {
return columns.map(({ name, type }) => {
const kibanaType = esFieldTypeToKibanaFieldType(type);
return {
id: name,
name,
meta: { type: kibanaType, esType: type },
} as DatatableColumn;
});
}
// Returns the columns exactly as being returned by the _query endpoint
// Based on the search api from the data plugin
export async function getESQLQueryColumnsRaw({
esqlQuery,
search,
@ -96,3 +61,69 @@ export async function getESQLQueryColumnsRaw({
);
}
}
// Returns the columns with the kibana format
// Based on the search api from the data plugin
export async function getESQLQueryColumns({
esqlQuery,
search,
signal,
}: {
esqlQuery: string;
search: ISearchGeneric;
signal?: AbortSignal;
}): Promise<DatatableColumn[]> {
try {
const rawColumns = await getESQLQueryColumnsRaw({ esqlQuery, search, signal });
const columns = formatESQLColumns(rawColumns) ?? [];
return columns;
} catch (error) {
throw new Error(
i18n.translate('esqlUtils.columnsErrorMsg', {
defaultMessage: 'Unable to load columns. {errorMessage}',
values: { errorMessage: error.message },
})
);
}
}
// Returns the table as being returned by the _query endpoint
// Based on the search api from the data plugin
export async function getESQLResults({
esqlQuery,
search,
signal,
filter,
dropNullColumns,
}: {
esqlQuery: string;
search: ISearchGeneric;
signal?: AbortSignal;
filter?: unknown;
dropNullColumns?: boolean;
}): Promise<{
response: ESQLSearchReponse;
params: ESQLSearchParams;
}> {
const result = await lastValueFrom(
search(
{
params: {
...(filter ? { filter } : {}),
query: esqlQuery,
version: ESQL_LATEST_VERSION,
...(dropNullColumns ? { dropNullColumns: true } : {}),
},
},
{
abortSignal: signal,
strategy: 'esql_async',
}
)
);
return {
response: result.rawResponse as unknown as ESQLSearchReponse,
params: result.requestParams as unknown as ESQLSearchParams,
};
}

View file

@ -6,13 +6,10 @@
* Side Public License, v 1.
*/
import { lastValueFrom } from 'rxjs';
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
import type { IKibanaSearchResponse, IKibanaSearchRequest } from '@kbn/search-types';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { ESQLSearchParams, ESQLSearchReponse } from '@kbn/es-types';
import type { AggregateQuery } from '@kbn/es-query';
import { ESQL_LATEST_VERSION, getESQLWithSafeLimit } from '@kbn/esql-utils';
import { getESQLWithSafeLimit, getESQLResults } from '@kbn/esql-utils';
import type { FieldStatsResponse } from '../../types';
import {
buildSearchFilter,
@ -63,27 +60,15 @@ export const loadFieldStatsTextBased: LoadFieldStatsTextBasedHandler = async ({
return {};
}
const searchHandler: SearchHandlerTextBased = async (body) => {
const searchHandler: SearchHandlerTextBased = async ({ query }) => {
const filter = buildSearchFilter({ timeFieldName: dataView.timeFieldName, fromDate, toDate });
const result = await lastValueFrom(
data.search.search<
IKibanaSearchRequest<ESQLSearchParams>,
IKibanaSearchResponse<ESQLSearchReponse>
>(
{
params: {
...(filter ? { filter } : {}),
...body,
version: ESQL_LATEST_VERSION,
},
},
{
abortSignal: abortController?.signal,
strategy: 'esql',
}
)
);
return result.rawResponse;
const result = await getESQLResults({
esqlQuery: query,
filter,
search: data.search.search,
signal: abortController?.signal,
});
return result.response;
};
if (!('esql' in baseQuery)) {