Fixes KQL autocomplete suggestions with IP fields (#154111)

## Summary

Resolves https://github.com/elastic/kibana/issues/140266.

Fixes KQL autocomplete suggestions when using an IP field. (Only works
when the selected value suggestion method is terms_enum, not terms_agg.)

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

### Release note

KQL autocomplete suggestions now support IP-type fields when the
advanced setting, autocomplete:valueSuggestionMethod, is set to
terms_enum.

---------

Co-authored-by: Julia Rechkunova <julia.rechkunova@gmail.com>
This commit is contained in:
Lukas Olson 2023-03-31 15:07:58 -07:00 committed by GitHub
parent 1384a44eed
commit c7114d2caa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 55 additions and 16 deletions

View file

@ -504,7 +504,7 @@ export function getUiSettings(
'The method used for querying suggestions for values in KQL autocomplete. Select terms_enum to use the ' +
'Elasticsearch terms enum API for improved autocomplete suggestion performance. (Note that terms_enum is ' +
'incompatible with Document Level Security.) Select terms_agg to use an Elasticsearch terms aggregation. ' +
'{learnMoreLink}',
'(Note that terms_agg is incompatible with IP-type fields.) {learnMoreLink}',
values: {
learnMoreLink:
`<a href=${docLinks.links.kibana.autocompleteSuggestions} target="_blank" rel="noopener">` +

View file

@ -69,15 +69,20 @@ describe('FieldSuggestions', () => {
expect(http.fetch).not.toHaveBeenCalled();
});
it('should return an empty array if the field type is not a string or boolean', async () => {
const [field] = stubFields.filter(({ type }) => type !== 'string' && type !== 'boolean');
const suggestions = await getValueSuggestions({
indexPattern: stubIndexPattern,
field,
query: '',
});
expect(suggestions).toEqual([]);
it('should return an empty array if the field type is not a string, boolean, or IP', async () => {
const fields = stubFields.filter(
({ type }) => type !== 'string' && type !== 'boolean' && type !== 'ip'
);
await Promise.all(
fields.map(async (field) => {
const suggestions = await getValueSuggestions({
indexPattern: stubIndexPattern,
field,
query: '',
});
expect(suggestions).toEqual([]);
})
);
expect(http.fetch).not.toHaveBeenCalled();
});
@ -93,7 +98,7 @@ describe('FieldSuggestions', () => {
expect(http.fetch).not.toHaveBeenCalled();
});
it('should otherwise request suggestions', async () => {
it('should request suggestions for strings', async () => {
const [field] = stubFields.filter(
({ type, aggregatable }) => type === 'string' && aggregatable
);
@ -108,6 +113,19 @@ describe('FieldSuggestions', () => {
expect(http.fetch).toHaveBeenCalled();
});
it('should request suggestions for ips', async () => {
const [field] = stubFields.filter(({ type, aggregatable }) => type === 'ip' && aggregatable);
await getValueSuggestions({
indexPattern: stubIndexPattern,
field,
query: '',
useTimeRange: false,
});
expect(http.fetch).toHaveBeenCalled();
});
it('should cache results if using the same index/field/query/filter', async () => {
const [field] = stubFields.filter(
({ type, aggregatable }) => type === 'string' && aggregatable

View file

@ -107,7 +107,7 @@ export const setupValueSuggestionProvider = (
} else if (
!shouldSuggestValues ||
!field.aggregatable ||
field.type !== 'string' ||
(field.type !== 'string' && field.type !== 'ip') ||
isVersionFieldType // suggestions don't work for version fields
) {
return [];

View file

@ -10,7 +10,7 @@ import { coreMock } from '@kbn/core/server/mocks';
import { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server';
import { ConfigSchema } from '../../config';
import type { DeeplyMockedKeys } from '@kbn/utility-types-jest';
import type { DataViewField } from '@kbn/data-views-plugin/common';
import type { DataViewField, FieldSpec } from '@kbn/data-views-plugin/common';
import { termsAggSuggestions } from './terms_agg';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { duration } from 'moment';
@ -136,4 +136,23 @@ describe('terms agg suggestions', () => {
]
`);
});
it('does not call the _search API when the field is an IP', async () => {
const result = await termsAggSuggestions(
configMock,
savedObjectsClientMock,
esClientMock,
'index',
'fieldName',
'query',
[],
{
type: 'ip',
name: 'fieldName',
} as FieldSpec
);
expect(esClientMock.search).not.toHaveBeenCalled();
expect(result).toMatchInlineSnapshot(`Array []`);
});
});

View file

@ -36,6 +36,11 @@ export async function termsAggSuggestions(
field = indexPattern && getFieldByName(fieldName, indexPattern);
}
// Terms agg doesn't support IP with "exclude"/"include" parameter
if (field?.type === 'ip') {
return [];
}
const body = await getBody(autocompleteSearchOptions, field ?? fieldName, query, filters);
const result = await esClient.search(

View file

@ -1228,7 +1228,6 @@
"dashboard.topNave.viewConfigDescription": "Basculer en mode Affichage uniquement",
"dashboard.unsavedChangesBadge": "Modifications non enregistrées",
"data.advancedSettings.autocompleteIgnoreTimerangeText": "Désactivez cette propriété pour obtenir des suggestions de saisie semi-automatique depuis l'intégralité de l'ensemble de données plutôt que depuis la plage temporelle définie. {learnMoreLink}",
"data.advancedSettings.autocompleteValueSuggestionMethodText": "La méthode utilisée pour générer des suggestions de valeur pour la saisie semi-automatique KQL. Sélectionnez terms_enum pour utiliser l'API d'énumération de termes d'Elasticsearch afin daméliorer les performances de suggestion de saisie semi-automatique. (Notez que terms_enum est incompatible avec la sécurité au niveau du document.) Sélectionnez terms_agg pour utiliser l'agrégation de termes d'Elasticsearch. {learnMoreLink}",
"data.advancedSettings.courier.customRequestPreferenceText": "{requestPreferenceLink} utilisé quand {setRequestReferenceSetting} est défini sur {customSettingValue}.",
"data.advancedSettings.courier.maxRequestsText": "Contrôle le paramètre {maxRequestsLink} utilisé pour les requêtes _msearch envoyées par Kibana. Définir ce paramètre sur 0 permet dutiliser la valeur Elasticsearch par défaut.",
"data.advancedSettings.query.allowWildcardsText": "Lorsque ce paramètre est activé, le caractère \"*\" est autorisé en tant que premier caractère dans une clause de requête. Pour interdire l'utilisation de caractères génériques au début des requêtes Lucene de base, utilisez {queryStringOptionsPattern}.",

View file

@ -1228,7 +1228,6 @@
"dashboard.topNave.viewConfigDescription": "表示専用モードに切り替え",
"dashboard.unsavedChangesBadge": "保存されていない変更",
"data.advancedSettings.autocompleteIgnoreTimerangeText": "このプロパティを無効にすると、現在の時間範囲からではなく、データセットからオートコンプリートの候補を取得します。{learnMoreLink}",
"data.advancedSettings.autocompleteValueSuggestionMethodText": "KQL自動入力で値の候補をクエリするために使用される方法。terms_enumを選択すると、Elasticsearch用語enum APIを使用して、自動入力候補のパフォーマンスを改善します。terms_enumはドキュメントレベルのセキュリティと互換性がありません。 terms_aggを選択すると、Elasticsearch用語アグリゲーションを使用します。{learnMoreLink}",
"data.advancedSettings.courier.customRequestPreferenceText": "{setRequestReferenceSetting}が{customSettingValue}に設定されているときに使用される{requestPreferenceLink}です。",
"data.advancedSettings.courier.maxRequestsText": "Kibanaから送信された_msearch requestsリクエストに使用される{maxRequestsLink}設定を管理します。この構成を無効にしてElasticsearchのデフォルトを使用するには、0に設定します。",
"data.advancedSettings.query.allowWildcardsText": "設定すると、クエリ句の頭に*が使えるようになります。基本的なLuceneクエリでリーディングワイルドカードを無効にするには、{queryStringOptionsPattern}を使用します。",

View file

@ -1228,7 +1228,6 @@
"dashboard.topNave.viewConfigDescription": "切换到仅查看模式",
"dashboard.unsavedChangesBadge": "未保存的更改",
"data.advancedSettings.autocompleteIgnoreTimerangeText": "禁用此属性可从您的完全数据集中获取自动完成建议,而非从当前时间范围。{learnMoreLink}",
"data.advancedSettings.autocompleteValueSuggestionMethodText": "用于在 KQL 自动完成中查询值建议的方法。选择 terms_enum 以使用 Elasticsearch 字词枚举 API 改善自动完成建议性能。请注意terms_enum 不兼容文档级别安全性。) 选择 terms_agg 以使用 Elasticsearch 字词聚合。{learnMoreLink}",
"data.advancedSettings.courier.customRequestPreferenceText": "将“{setRequestReferenceSetting}设置为“{customSettingValue}时,将使用“{requestPreferenceLink}”。",
"data.advancedSettings.courier.maxRequestsText": "控制用于 Kibana 发送的 _msearch 请求的“{maxRequestsLink}”设置。设置为 0 可禁用此配置并使用 Elasticsearch 默认值。",
"data.advancedSettings.query.allowWildcardsText": "设置后,将允许 * 用作查询语句的第一个字符。要在基本 lucene 查询中禁用前导通配符,请使用“{queryStringOptionsPattern}”。",