filter types (#111269)

This commit is contained in:
Peter Pisljar 2021-10-06 17:46:54 +02:00 committed by GitHub
parent b59e3ff460
commit 1a577dfbfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
96 changed files with 501 additions and 634 deletions

View file

@ -41,8 +41,10 @@ describe('build query', () => {
{ query: 'bar:baz', language: 'lucene' },
] as Query[];
const filters = {
match: {
a: 'b',
query: {
match: {
a: 'b',
},
},
meta: {
alias: '',
@ -80,8 +82,10 @@ describe('build query', () => {
it('should accept queries and filters as either single objects or arrays', () => {
const queries = { query: 'extension:jpg', language: 'lucene' } as Query;
const filters = {
match: {
a: 'b',
query: {
match: {
a: 'b',
},
},
meta: {
alias: '',
@ -118,12 +122,14 @@ describe('build query', () => {
it('should remove match_all clauses', () => {
const filters = [
{
match_all: {},
query: { match_all: {} },
meta: { type: 'match_all' },
} as MatchAllFilter,
{
match: {
a: 'b',
query: {
match: {
a: 'b',
},
},
meta: {
alias: '',
@ -163,7 +169,7 @@ describe('build query', () => {
{ query: '@timestamp:"2019-03-23T13:18:00"', language: 'kuery' },
{ query: '@timestamp:"2019-03-23T13:18:00"', language: 'lucene' },
] as Query[];
const filters = [{ match_all: {}, meta: { type: 'match_all' } } as MatchAllFilter];
const filters = [{ query: { match_all: {} }, meta: { type: 'match_all' } } as MatchAllFilter];
const config = {
allowLeadingWildcards: true,
queryStringOptions: {},

View file

@ -31,11 +31,11 @@ describe('build query', () => {
test('should transform an array of kibana filters into ES queries combined in the bool clauses', () => {
const filters = [
{
match_all: {},
query: { match_all: {} },
meta: { type: 'match_all' },
} as MatchAllFilter,
{
exists: { field: 'foo' },
query: { exists: { field: 'foo' } },
meta: { type: 'exists' },
} as ExistsFilter,
] as Filter[];
@ -50,7 +50,7 @@ describe('build query', () => {
test('should remove disabled filters', () => {
const filters = [
{
match_all: {},
query: { match_all: {} },
meta: { type: 'match_all', negate: true, disabled: true },
} as MatchAllFilter,
] as Filter[];
@ -70,7 +70,7 @@ describe('build query', () => {
test('should place negated filters in the must_not clause', () => {
const filters = [
{
match_all: {},
query: { match_all: {} },
meta: { type: 'match_all', negate: true },
} as MatchAllFilter,
] as Filter[];
@ -104,10 +104,10 @@ describe('build query', () => {
test('should migrate deprecated match syntax', () => {
const filters = [
{
query: { match: { extension: { query: 'foo', type: 'phrase' } } },
match: { extension: { query: 'foo', type: 'phrase' } },
meta: { type: 'phrase' },
},
] as Filter[];
] as unknown as Filter[];
const expectedESQueries = [
{
@ -137,7 +137,7 @@ describe('build query', () => {
test('should wrap filters targeting nested fields in a nested query', () => {
const filters = [
{
exists: { field: 'nestedField.child' },
query: { exists: { field: 'nestedField.child' } },
meta: { type: 'exists', alias: '', disabled: false, negate: false },
},
];

View file

@ -35,12 +35,7 @@ const filterNegate = (reverse: boolean) => (filter: Filter) => {
* @return {Object} the query version of that filter
*/
const translateToQuery = (filter: Partial<Filter>): estypes.QueryDslQueryContainer => {
if (filter.query) {
return filter.query as estypes.QueryDslQueryContainer;
}
// TODO: investigate what's going on here! What does this mean for filters that don't have a query!
return filter as estypes.QueryDslQueryContainer;
return filter.query || filter;
};
/**

View file

@ -25,11 +25,13 @@ describe('handleNestedFilter', function () {
meta: {
index: 'logstash-*',
},
nested: {
path: 'nestedField',
query: {
match_phrase: {
'nestedField.child': 'foo',
query: {
nested: {
path: 'nestedField',
query: {
match_phrase: {
'nestedField.child': 'foo',
},
},
},
},
@ -65,10 +67,8 @@ describe('handleNestedFilter', function () {
// for example, we don't support query_string queries
const filter = buildQueryFilter(
{
query: {
query_string: {
query: 'response:200',
},
query_string: {
query: 'response:200',
},
},
'logstash-*',

View file

@ -29,9 +29,11 @@ export const handleNestedFilter = (filter: Filter, indexPattern?: IndexPatternBa
return {
meta: filter.meta,
nested: {
path: field.subType.nested.path,
query: query.query || query,
query: {
nested: {
path: field.subType.nested.path,
query: query.query || query,
},
},
};
};

View file

@ -6,6 +6,7 @@
* Side Public License, v 1.
*/
export { migrateFilter } from './migrate_filter';
export { buildEsQuery, EsQueryConfig } from './build_es_query';
export { buildQueryFromFilters } from './from_filters';
export { luceneStringToDsl } from './lucene_string_to_dsl';

View file

@ -12,6 +12,16 @@ import { PhraseFilter, MatchAllFilter } from '../filters';
describe('migrateFilter', function () {
const oldMatchPhraseFilter = {
match: {
fieldFoo: {
query: 'foobar',
type: 'phrase',
},
},
meta: {},
} as unknown as DeprecatedMatchPhraseFilter;
const oldMatchPhraseFilter2 = {
query: {
match: {
fieldFoo: {
@ -36,8 +46,10 @@ describe('migrateFilter', function () {
it('should migrate match filters of type phrase', function () {
const migratedFilter = migrateFilter(oldMatchPhraseFilter, undefined);
expect(migratedFilter).toEqual(newMatchPhraseFilter);
const migratedFilter2 = migrateFilter(oldMatchPhraseFilter2, undefined);
expect(migratedFilter2).toEqual(newMatchPhraseFilter);
});
it('should not modify the original filter', function () {
@ -50,7 +62,7 @@ describe('migrateFilter', function () {
it('should return the original filter if no migration is necessary', function () {
const originalFilter = {
match_all: {},
query: { match_all: {} },
} as MatchAllFilter;
const migratedFilter = migrateFilter(originalFilter, undefined);

View file

@ -13,26 +13,31 @@ import { IndexPatternBase } from './types';
/** @internal */
export interface DeprecatedMatchPhraseFilter extends Filter {
query: {
match: {
[field: string]: {
query: any;
type: 'phrase';
};
match: {
[field: string]: {
query: any;
type: 'phrase';
};
};
}
function isDeprecatedMatchPhraseFilter(filter: Filter): filter is DeprecatedMatchPhraseFilter {
const fieldName = Object.keys(filter.query?.match ?? {})[0];
return Boolean(fieldName && get(filter, ['query', 'match', fieldName, 'type']) === 'phrase');
// @ts-ignore
const fieldName = Object.keys((filter.match || filter.query?.match) ?? {})[0];
return Boolean(
fieldName &&
(get(filter, ['query', 'match', fieldName, 'type']) === 'phrase' ||
get(filter, ['match', fieldName, 'type']) === 'phrase')
);
}
/** @internal */
export function migrateFilter(filter: Filter, indexPattern?: IndexPatternBase) {
if (isDeprecatedMatchPhraseFilter(filter)) {
const fieldName = Object.keys(filter.query.match)[0];
const params: Record<string, any> = get(filter, ['query', 'match', fieldName]);
// @ts-ignore
const match = filter.match || filter.query.match;
const fieldName = Object.keys(match)[0];
const params: Record<string, any> = get(match, [fieldName]);
let query = params.query;
if (indexPattern) {
const field = indexPattern.fields.find((f) => f.name === fieldName);
@ -42,7 +47,8 @@ export function migrateFilter(filter: Filter, indexPattern?: IndexPatternBase) {
}
}
return {
...filter,
meta: filter.meta,
$state: filter.$state,
query: {
match_phrase: {
[fieldName]: omit(
@ -57,5 +63,44 @@ export function migrateFilter(filter: Filter, indexPattern?: IndexPatternBase) {
};
}
if (!filter.query) {
filter.query = {};
}
// @ts-ignore
if (filter.exists) {
// @ts-ignore
filter.query.exists = filter.exists;
// @ts-ignore
delete filter.exists;
}
// @ts-ignore
if (filter.range) {
// @ts-ignore
filter.query.range = filter.range;
// @ts-ignore
delete filter.range;
}
// @ts-ignore
if (filter.match_all) {
// @ts-ignore
filter.query.match_all = filter.match_all;
// @ts-ignore
delete filter.match_all;
}
// move all other keys under query
Object.keys(filter).forEach((key) => {
if (key === 'meta' || key === 'query' || key === '$state') {
return;
}
// @ts-ignore
filter.query[key] = filter[key];
// @ts-ignore
delete filter[key];
});
return filter;
}

View file

@ -13,8 +13,10 @@ import type { Filter, FilterMeta } from './types';
/** @public */
export type ExistsFilter = Filter & {
meta: FilterMeta;
exists?: {
field: string;
query: {
exists?: {
field: string;
};
};
};
@ -24,13 +26,14 @@ export type ExistsFilter = Filter & {
*
* @public
*/
export const isExistsFilter = (filter: Filter): filter is ExistsFilter => has(filter, 'exists');
export const isExistsFilter = (filter: Filter): filter is ExistsFilter =>
has(filter, 'query.exists');
/**
* @internal
*/
export const getExistsFilterField = (filter: ExistsFilter) => {
return filter.exists && filter.exists.field;
return filter.query.exists && filter.query.exists.field;
};
/**
@ -46,8 +49,10 @@ export const buildExistsFilter = (field: IndexPatternFieldBase, indexPattern: In
meta: {
index: indexPattern.id,
},
exists: {
field: field.name,
query: {
exists: {
field: field.name,
},
},
} as ExistsFilter;
};

View file

@ -28,10 +28,8 @@ describe('getFilterField', function () {
it('should return undefined for filters that do not target a specific field', () => {
const filter = buildQueryFilter(
{
query: {
query_string: {
query: 'response:200 and extension:jpg',
},
query_string: {
query: 'response:200 and extension:jpg',
},
},
indexPattern.id!,

View file

@ -7,7 +7,6 @@
*/
import { getExistsFilterField, isExistsFilter } from './exists_filter';
import { getMissingFilterField, isMissingFilter } from './missing_filter';
import { getPhrasesFilterField, isPhrasesFilter } from './phrases_filter';
import { getPhraseFilterField, isPhraseFilter } from './phrase_filter';
import { getRangeFilterField, isRangeFilter } from './range_filter';
@ -27,9 +26,6 @@ export const getFilterField = (filter: Filter) => {
if (isRangeFilter(filter)) {
return getRangeFilterField(filter);
}
if (isMissingFilter(filter)) {
return getMissingFilterField(filter);
}
return;
};

View file

@ -14,7 +14,6 @@ export * from './exists_filter';
export * from './get_filter_field';
export * from './get_filter_params';
export * from './match_all_filter';
export * from './missing_filter';
export * from './phrase_filter';
export * from './phrases_filter';
export * from './query_string_filter';

View file

@ -17,7 +17,9 @@ export interface MatchAllFilterMeta extends FilterMeta {
export type MatchAllFilter = Filter & {
meta: MatchAllFilterMeta;
match_all: estypes.QueryDslMatchAllQuery;
query: {
match_all: estypes.QueryDslMatchAllQuery;
};
};
/**
@ -27,4 +29,4 @@ export type MatchAllFilter = Filter & {
* @public
*/
export const isMatchAllFilter = (filter: Filter): filter is MatchAllFilter =>
has(filter, 'match_all');
has(filter, 'query.match_all');

View file

@ -1,28 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { getMissingFilterField } from './missing_filter';
describe('missing filter', function () {
describe('getMissingFilterField', function () {
it('should return the name of the field an missing query is targeting', () => {
const filter = {
missing: {
field: 'extension',
},
meta: {
disabled: false,
negate: false,
alias: null,
},
};
const result = getMissingFilterField(filter);
expect(result).toBe('extension');
});
});
});

View file

@ -1,34 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { has } from 'lodash';
import type { Filter, FilterMeta } from './types';
export type MissingFilterMeta = FilterMeta;
export type MissingFilter = Filter & {
meta: MissingFilterMeta;
missing: {
field: string;
};
};
/**
* @param filter
* @returns `true` if a filter is an `MissingFilter`
*
* @public
*/
export const isMissingFilter = (filter: Filter): filter is MissingFilter => has(filter, 'missing');
/**
* @internal
*/
export const getMissingFilterField = (filter: MissingFilter) => {
return filter.missing && filter.missing.field;
};

View file

@ -83,13 +83,15 @@ describe('Phrase filter builder', () => {
index: 'id',
field: 'script number',
},
script: {
query: {
script: {
lang: 'expression',
params: {
value: 5,
script: {
lang: 'expression',
params: {
value: 5,
},
source: '(1234) == value',
},
source: '(1234) == value',
},
},
});
@ -103,13 +105,15 @@ describe('Phrase filter builder', () => {
index: 'id',
field: 'script number',
},
script: {
query: {
script: {
lang: 'expression',
params: {
value: 5,
script: {
lang: 'expression',
params: {
value: 5,
},
source: '(1234) == value',
},
source: '(1234) == value',
},
},
});

View file

@ -100,7 +100,7 @@ export const buildPhraseFilter = (
if (field.scripted) {
return {
meta: { index: indexPattern.id, field: field.name } as PhraseFilterMeta,
script: getPhraseScript(field, value),
query: { script: getPhraseScript(field, value) },
};
} else {
return {

View file

@ -14,13 +14,15 @@ describe('Query string filter builder', () => {
});
it('should return a query filter when passed a standard field', () => {
expect(buildQueryFilter({ foo: 'bar' }, 'index', '')).toEqual({
expect(buildQueryFilter({ query_string: { query: 'bar' } }, 'index', '')).toEqual({
meta: {
alias: '',
index: 'index',
},
query: {
foo: 'bar',
query_string: {
query: 'bar',
},
},
});
});

View file

@ -38,10 +38,12 @@ describe('Range filter builder', () => {
index: 'id',
params: {},
},
range: {
bytes: {
gte: 1,
lte: 3,
query: {
range: {
bytes: {
gte: 1,
lte: 3,
},
},
},
});
@ -56,14 +58,16 @@ describe('Range filter builder', () => {
index: 'id',
params: {},
},
script: {
query: {
script: {
lang: 'expression',
source: '(' + field!.script + ')>=gte && (' + field!.script + ')<=lte',
params: {
value: '>=1 <=3',
gte: 1,
lte: 3,
script: {
lang: 'expression',
source: '(' + field!.script + ')>=gte && (' + field!.script + ')<=lte',
params: {
value: '>=1 <=3',
gte: 1,
lte: 3,
},
},
},
},
@ -79,14 +83,16 @@ describe('Range filter builder', () => {
index: 'id',
params: {},
},
script: {
query: {
script: {
lang: 'expression',
source: '(' + field!.script + ')>=gte && (' + field!.script + ')<=lte',
params: {
value: '>=1 <=3',
gte: 1,
lte: 3,
script: {
lang: 'expression',
source: '(' + field!.script + ')>=gte && (' + field!.script + ')<=lte',
params: {
value: '>=1 <=3',
gte: 1,
lte: 3,
},
},
},
},
@ -106,7 +112,7 @@ describe('Range filter builder', () => {
{ gte: 1, lte: 3 },
indexPattern
) as ScriptedRangeFilter;
expect(rangeFilter.script.script.source).toBe(expected);
expect(rangeFilter.query.script.script.source).toBe(expected);
});
it('should throw an error when gte and gt, or lte and lt are both passed', () => {
@ -130,7 +136,7 @@ describe('Range filter builder', () => {
};
const filter = buildRangeFilter(field!, params, indexPattern) as ScriptedRangeFilter;
const script = filter.script!.script;
const script = filter.query.script!.script;
expect(script.source).toBe('(' + field!.script + ')' + operator + key);
expect(script.params?.[key]).toBe(5);
@ -153,21 +159,21 @@ describe('Range filter builder', () => {
describe('returned filter', () => {
it('is a script filter', () => {
expect(filter).toHaveProperty('script');
expect(filter.query).toHaveProperty('script');
});
it('contain a param for the finite side', () => {
expect(filter.script!.script.params).toHaveProperty('gte', 0);
expect(filter.query.script!.script.params).toHaveProperty('gte', 0);
});
it('does not contain a param for the infinite side', () => {
expect(filter.script!.script.params).not.toHaveProperty('lt');
expect(filter.query.script!.script.params).not.toHaveProperty('lt');
});
it('does not contain a script condition for the infinite side', () => {
const script = field!.script;
expect(filter.script!.script.source).toEqual(`(${script})>=gte`);
expect(filter.query.script!.script.source).toEqual(`(${script})>=gte`);
});
});
});
@ -187,12 +193,12 @@ describe('Range filter builder', () => {
describe('returned filter', () => {
it('is a match_all filter', () => {
expect(filter).not.toHaveProperty('script');
expect(filter).toHaveProperty('match_all');
expect(filter.query).not.toHaveProperty('script');
expect(filter.query).toHaveProperty('match_all');
});
it('does not contain params', () => {
expect(filter).not.toHaveProperty('params');
expect(filter.query).not.toHaveProperty('params');
});
it('meta field is set to field name', () => {

View file

@ -60,14 +60,18 @@ export type RangeFilterMeta = FilterMeta & {
export type ScriptedRangeFilter = Filter & {
meta: RangeFilterMeta;
script: {
script: estypes.InlineScript;
query: {
script: {
script: estypes.InlineScript;
};
};
};
export type MatchAllRangeFilter = Filter & {
meta: RangeFilterMeta;
match_all: estypes.QueryDslQueryContainer['match_all'];
query: {
match_all: estypes.QueryDslQueryContainer['match_all'];
};
};
/**
@ -75,7 +79,9 @@ export type MatchAllRangeFilter = Filter & {
*/
export type RangeFilter = Filter & {
meta: RangeFilterMeta;
range: { [key: string]: RangeFilterParams };
query: {
range: { [key: string]: RangeFilterParams };
};
};
/**
@ -84,7 +90,7 @@ export type RangeFilter = Filter & {
*
* @public
*/
export const isRangeFilter = (filter?: Filter): filter is RangeFilter => has(filter, 'range');
export const isRangeFilter = (filter?: Filter): filter is RangeFilter => has(filter, 'query.range');
/**
*
@ -94,7 +100,7 @@ export const isRangeFilter = (filter?: Filter): filter is RangeFilter => has(fil
* @public
*/
export const isScriptedRangeFilter = (filter: Filter): filter is ScriptedRangeFilter => {
const params: RangeFilterParams = get(filter, 'script.script.params', {});
const params: RangeFilterParams = get(filter, 'query.script.script.params', {});
return hasRangeKeys(params);
};
@ -103,7 +109,7 @@ export const isScriptedRangeFilter = (filter: Filter): filter is ScriptedRangeFi
* @internal
*/
export const getRangeFilterField = (filter: RangeFilter) => {
return filter.range && Object.keys(filter.range)[0];
return filter.query.range && Object.keys(filter.query.range)[0];
};
const formatValue = (params: any[]) =>
@ -154,14 +160,14 @@ export const buildRangeFilter = (
};
if (totalInfinite === OPERANDS_IN_RANGE) {
return { meta, match_all: {} } as MatchAllRangeFilter;
return { meta, query: { match_all: {} } } as MatchAllRangeFilter;
} else if (field.scripted) {
const scr = getRangeScript(field, params);
// TODO: type mismatch enforced
scr.script.params.value = formatValue(scr.script.params as any);
return { meta, script: scr } as ScriptedRangeFilter;
return { meta, query: { script: scr } } as ScriptedRangeFilter;
} else {
return { meta, range: { [field.name]: params } } as RangeFilter;
return { meta, query: { range: { [field.name]: params } } } as RangeFilter;
}
};

View file

@ -11,7 +11,6 @@ import { PhrasesFilter } from './phrases_filter';
import { PhraseFilter } from './phrase_filter';
import { RangeFilter } from './range_filter';
import { MatchAllFilter } from './match_all_filter';
import { MissingFilter } from './missing_filter';
/**
* A common type for filters supported by this package
@ -22,8 +21,7 @@ export type FieldFilter =
| PhraseFilter
| PhrasesFilter
| RangeFilter
| MatchAllFilter
| MissingFilter;
| MatchAllFilter;
/**
* An enum of all types of filters supported by this package
@ -35,7 +33,6 @@ export enum FILTERS {
PHRASE = 'phrase',
EXISTS = 'exists',
MATCH_ALL = 'match_all',
MISSING = 'missing',
QUERY_STRING = 'query_string',
RANGE = 'range',
RANGE_FROM_VALUE = 'range_from_value',
@ -74,8 +71,6 @@ export type Filter = {
store: FilterStateStore;
};
meta: FilterMeta;
// TODO: research me! This is being extracted into the top level by translateToQuery. Maybe we can simplify.
query?: Record<string, any>;
};

View file

@ -12,37 +12,21 @@ import { buildEmptyFilter, buildQueryFilter, FilterStateStore } from '..';
describe('filter manager utilities', () => {
describe('compare filters', () => {
test('should compare filters', () => {
const f1 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);
const f1 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
const f2 = buildEmptyFilter(true);
expect(compareFilters(f1, f2)).toBeFalsy();
});
test('should compare duplicates', () => {
const f1 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);
const f2 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);
const f1 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
const f2 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
expect(compareFilters(f1, f2)).toBeTruthy();
});
test('should compare filters, where one filter is null', () => {
const f1 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);
const f1 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
const f2 = null;
expect(compareFilters(f1, f2 as any)).toBeFalsy();
});
@ -54,16 +38,8 @@ describe('filter manager utilities', () => {
});
test('should compare duplicates, ignoring meta attributes', () => {
const f1 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index1',
''
);
const f2 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index2',
''
);
const f1 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index1', '');
const f2 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index2', '');
expect(compareFilters(f1, f2)).toBeTruthy();
});
@ -71,75 +47,43 @@ describe('filter manager utilities', () => {
test('should compare duplicates, ignoring $state attributes', () => {
const f1 = {
$state: { store: FilterStateStore.APP_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
expect(compareFilters(f1, f2)).toBeTruthy();
});
test('should compare filters array to non array', () => {
const f1 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);
const f1 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
const f2 = buildQueryFilter(
{ _type: { match: { query: 'mochi', type: 'phrase' } } },
'index',
''
);
const f2 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
expect(compareFilters([f1, f2], f1)).toBeFalsy();
});
test('should compare filters array to partial array', () => {
const f1 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);
const f1 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
const f2 = buildQueryFilter(
{ _type: { match: { query: 'mochi', type: 'phrase' } } },
'index',
''
);
const f2 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
expect(compareFilters([f1, f2], [f1])).toBeFalsy();
});
test('should compare filters array to exact array', () => {
const f1 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
);
const f1 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
const f2 = buildQueryFilter(
{ _type: { match: { query: 'mochi', type: 'phrase' } } },
'index',
''
);
const f2 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index', '');
expect(compareFilters([f1, f2], [f1, f2])).toBeTruthy();
});
test('should compare array of duplicates, ignoring meta attributes', () => {
const f1 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index1',
''
);
const f2 = buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index2',
''
);
const f1 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index1', '');
const f2 = buildQueryFilter({ query_string: { query: 'apache' } }, 'index2', '');
expect(compareFilters([f1], [f2])).toBeTruthy();
});
@ -147,11 +91,11 @@ describe('filter manager utilities', () => {
test('should compare array of duplicates, ignoring $state attributes', () => {
const f1 = {
$state: { store: FilterStateStore.APP_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
expect(compareFilters([f1], [f2])).toBeTruthy();
@ -160,11 +104,11 @@ describe('filter manager utilities', () => {
test('should compare duplicates with COMPARE_ALL_OPTIONS should check store', () => {
const f1 = {
$state: { store: FilterStateStore.APP_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
expect(compareFilters([f1], [f2], COMPARE_ALL_OPTIONS)).toBeFalsy();
@ -173,11 +117,11 @@ describe('filter manager utilities', () => {
test('should compare duplicates with COMPARE_ALL_OPTIONS should not check key and value ', () => {
const f1 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
f2.meta.key = 'wassup';
@ -189,11 +133,11 @@ describe('filter manager utilities', () => {
test('should compare alias with alias true', () => {
const f1 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
f2.meta.alias = 'wassup';
@ -205,11 +149,11 @@ describe('filter manager utilities', () => {
test('should compare alias with COMPARE_ALL_OPTIONS', () => {
const f1 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
f2.meta.alias = 'wassup';
@ -221,11 +165,11 @@ describe('filter manager utilities', () => {
test('should compare index with index true', () => {
const f1 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
f2.meta.index = 'wassup';

View file

@ -28,7 +28,7 @@ describe('filter manager utilities', () => {
indexPattern,
''
),
buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index', ''),
buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
];
const filters: Filter[] = [
buildRangeFilter(
@ -37,7 +37,7 @@ describe('filter manager utilities', () => {
indexPattern,
''
),
buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index', ''),
buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
];
const results = dedupFilters(existing, filters);
@ -54,11 +54,7 @@ describe('filter manager utilities', () => {
''
),
{
...buildQueryFilter(
{ match: { _term: { query: 'apache', type: 'phrase' } } },
'index1',
''
),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index1', ''),
meta: { disabled: true, negate: false, alias: null },
},
];
@ -69,7 +65,7 @@ describe('filter manager utilities', () => {
indexPattern,
''
),
buildQueryFilter({ match: { _term: { query: 'apache', type: 'phrase' } } }, 'index1', ''),
buildQueryFilter({ query_string: { query: 'apache' } }, 'index1', ''),
];
const results = dedupFilters(existing, filters);
@ -86,11 +82,7 @@ describe('filter manager utilities', () => {
''
),
{
...buildQueryFilter(
{ match: { _term: { query: 'apache', type: 'phrase' } } },
'index',
''
),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
$state: { store: FilterStateStore.APP_STATE },
},
];
@ -102,11 +94,7 @@ describe('filter manager utilities', () => {
''
),
{
...buildQueryFilter(
{ match: { _term: { query: 'apache', type: 'phrase' } } },
'index',
''
),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
$state: { store: FilterStateStore.GLOBAL_STATE },
},
];

View file

@ -13,8 +13,8 @@ describe('filter manager utilities', () => {
describe('niqFilter', () => {
test('should filter out dups', () => {
const before: Filter[] = [
buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
];
const results = uniqFilters(before);
@ -23,8 +23,8 @@ describe('filter manager utilities', () => {
test('should filter out duplicates, ignoring meta attributes', () => {
const before: Filter[] = [
buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index1', ''),
buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index2', ''),
buildQueryFilter({ query_string: { query: 'apache' } }, 'index1', ''),
buildQueryFilter({ query_string: { query: 'apache' } }, 'index2', ''),
];
const results = uniqFilters(before);
@ -35,19 +35,11 @@ describe('filter manager utilities', () => {
const before: Filter[] = [
{
$state: { store: FilterStateStore.APP_STATE },
...buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
},
{
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'index',
''
),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
},
];
const results = uniqFilters(before);

View file

@ -30,7 +30,6 @@ export {
export {
isExistsFilter,
isMatchAllFilter,
isMissingFilter,
isPhraseFilter,
isPhrasesFilter,
isRangeFilter,
@ -69,7 +68,6 @@ export {
RangeFilterMeta,
MatchAllFilter,
CustomFilter,
MissingFilter,
RangeFilterParams,
QueryStringFilter,
} from './build_filters';

View file

@ -20,4 +20,5 @@ export const existsFilter: ExistsFilter = {
$state: {
store: FilterStateStore.APP_STATE,
},
query: {},
};

View file

@ -25,5 +25,5 @@ export const rangeFilter: RangeFilter = {
$state: {
store: FilterStateStore.APP_STATE,
},
range: {},
query: { range: {} },
};

View file

@ -23,6 +23,7 @@ import {
} from '@kbn/securitysolution-io-ts-list-types';
import { Filter } from '@kbn/es-query';
import { QueryDslBoolQuery, QueryDslNestedQuery } from '@elastic/elasticsearch/api/types';
import { hasLargeValueList } from '../has_large_value_list';
type NonListEntry = EntryMatch | EntryMatchAny | EntryNested | EntryExists;
@ -39,21 +40,11 @@ export type ExceptionItemSansLargeValueLists =
| CreateExceptionListItemNonLargeList;
export interface BooleanFilter {
bool: {
must?: unknown | unknown[];
must_not?: unknown | unknown[];
should?: unknown[];
filter?: unknown | unknown[];
minimum_should_match?: number;
};
bool: QueryDslBoolQuery;
}
export interface NestedFilter {
nested: {
path: string;
query: unknown | unknown[];
score_mode: string;
};
nested: QueryDslNestedQuery;
}
export const chunkExceptions = (
@ -178,7 +169,7 @@ export const buildExceptionFilter = ({
return undefined;
} else if (exceptionsWithoutLargeValueLists.length <= chunkSize) {
const clause = createOrClauses(exceptionsWithoutLargeValueLists);
exceptionFilter.query!.bool.should = clause;
exceptionFilter.query!.bool!.should = clause;
return exceptionFilter;
} else {
const chunks = chunkExceptions(exceptionsWithoutLargeValueLists, chunkSize);

View file

@ -29,7 +29,6 @@ import {
isFilters as oldIsFilters,
isExistsFilter as oldIsExistsFilter,
isMatchAllFilter as oldIsMatchAllFilter,
isMissingFilter as oldIsMissingFilter,
isPhraseFilter as oldIsPhraseFilter,
isPhrasesFilter as oldIsPhrasesFilter,
isRangeFilter as oldIsRangeFilter,
@ -51,7 +50,6 @@ import {
PhraseFilter as oldPhraseFilter,
MatchAllFilter as oldMatchAllFilter,
CustomFilter as oldCustomFilter,
MissingFilter as oldMissingFilter,
RangeFilter as oldRangeFilter,
KueryNode as oldKueryNode,
FilterMeta as oldFilterMeta,
@ -172,12 +170,6 @@ const isExistsFilter = oldIsExistsFilter;
*/
const isMatchAllFilter = oldIsMatchAllFilter;
/**
* @deprecated Import from the "@kbn/es-query" package directly instead.
* @removeBy 8.1
*/
const isMissingFilter = oldIsMissingFilter;
/**
* @deprecated Import from the "@kbn/es-query" package directly instead.
* @removeBy 8.1
@ -346,12 +338,6 @@ type MatchAllFilter = oldMatchAllFilter;
*/
type CustomFilter = oldCustomFilter;
/**
* @deprecated Import from the "@kbn/es-query" package directly instead.
* @removeBy 8.1
*/
type MissingFilter = oldMissingFilter;
/**
* @deprecated Import from the "@kbn/es-query" package directly instead.
* @removeBy 8.1
@ -408,7 +394,6 @@ export {
isFilters,
isExistsFilter,
isMatchAllFilter,
isMissingFilter,
isPhraseFilter,
isPhrasesFilter,
isRangeFilter,
@ -437,7 +422,6 @@ export {
PhraseFilter,
MatchAllFilter,
CustomFilter,
MissingFilter,
RangeFilter,
KueryNode,
FilterMeta,

View file

@ -20,4 +20,5 @@ export const existsFilter: ExistsFilter = {
$state: {
store: FilterStateStore.APP_STATE,
},
query: {},
};

View file

@ -25,5 +25,5 @@ export const rangeFilter: RangeFilter = {
$state: {
store: FilterStateStore.APP_STATE,
},
range: {},
query: { range: {} },
};

View file

@ -35,7 +35,7 @@ describe('get_time', () => {
} as unknown as IIndexPattern,
{ from: 'now-60y', to: 'now' }
) as RangeFilter;
expect(filter.range.date).toEqual({
expect(filter.query.range.date).toEqual({
gte: '1940-02-01T00:00:00.000Z',
lte: '2000-02-01T00:00:00.000Z',
format: 'strict_date_optional_time',
@ -73,7 +73,7 @@ describe('get_time', () => {
{ from: 'now-60y', to: 'now' },
{ fieldName: 'myCustomDate' }
) as RangeFilter;
expect(filter.range.myCustomDate).toEqual({
expect(filter.query.range.myCustomDate).toEqual({
gte: '1940-02-01T00:00:00.000Z',
lte: '2000-02-01T00:00:00.000Z',
format: 'strict_date_optional_time',
@ -111,7 +111,7 @@ describe('get_time', () => {
{ fieldName: 'myCustomDate' }
) as RangeFilter;
expect(filter.range.myCustomDate).toEqual({
expect(filter.query.range.myCustomDate).toEqual({
gte: 'now-60y',
lte: 'now',
format: 'strict_date_optional_time',
@ -150,7 +150,7 @@ describe('get_time', () => {
{ fieldName: 'myCustomDate' }
) as RangeFilter;
expect(filter.range.myCustomDate).toEqual({
expect(filter.query.range.myCustomDate).toEqual({
gte: '2020-09-01T08:30:00.000Z',
lte: 'now',
format: 'strict_date_optional_time',

View file

@ -406,8 +406,8 @@ export class AggConfigs {
.map(([filter, field]) => ({
range: {
[field]: {
gte: moment(filter?.range[field].gte).subtract(shift).toISOString(),
lte: moment(filter?.range[field].lte).subtract(shift).toISOString(),
gte: moment(filter?.query.range[field].gte).subtract(shift).toISOString(),
lte: moment(filter?.query.range[field].lte).subtract(shift).toISOString(),
},
},
})),

View file

@ -69,10 +69,10 @@ describe('AggConfig Filters', () => {
test('creates a valid range filter', () => {
init();
expect(filter).toHaveProperty('range');
expect(filter.range).toHaveProperty(field.name);
expect(filter.query).toHaveProperty('range');
expect(filter.query.range).toHaveProperty(field.name);
const fieldParams = filter.range[field.name];
const fieldParams = filter.query.range[field.name];
expect(fieldParams).toHaveProperty('gte');
expect(typeof fieldParams.gte).toBe('string');
@ -100,7 +100,7 @@ describe('AggConfig Filters', () => {
init(option.val, duration);
const interval = agg.buckets.getInterval();
const params = filter.range[field.name];
const params = filter.query.range[field.name];
expect(params.gte).toBe(bucketStart.toISOString());
expect(params.lt).toBe(bucketStart.clone().add(interval).toISOString());

View file

@ -57,12 +57,12 @@ describe('AggConfig Filters', () => {
to: to.valueOf(),
}) as RangeFilter;
expect(filter).toHaveProperty('range');
expect(filter.query).toHaveProperty('range');
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter.range).toHaveProperty('@timestamp');
expect(filter.range['@timestamp']).toHaveProperty('gte', moment(from).toISOString());
expect(filter.range['@timestamp']).toHaveProperty('lt', moment(to).toISOString());
expect(filter.query.range).toHaveProperty('@timestamp');
expect(filter.query.range['@timestamp']).toHaveProperty('gte', moment(from).toISOString());
expect(filter.query.range['@timestamp']).toHaveProperty('lt', moment(to).toISOString());
});
});
});

View file

@ -79,7 +79,7 @@ describe('AggConfig Filters', () => {
}
`);
expect(filter.query?.bool.must[0].query_string.query).toBe('type:nginx');
expect((filter.query?.bool?.must as any)[0].query_string.query).toBe('type:nginx');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter.meta).toHaveProperty('alias', 'type:nginx');
});

View file

@ -18,10 +18,10 @@ function validateFilter(filter: RangeFilter) {
expect(mockGetFieldFormatsStart().deserialize).toHaveBeenCalledTimes(1);
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter).toHaveProperty('range');
expect(filter.range).toHaveProperty('bytes');
expect(filter.range.bytes).toHaveProperty('gte', 2048);
expect(filter.range.bytes).toHaveProperty('lt', 3072);
expect(filter.query).toHaveProperty('range');
expect(filter.query.range).toHaveProperty('bytes');
expect(filter.query.range.bytes).toHaveProperty('gte', 2048);
expect(filter.query.range.bytes).toHaveProperty('lt', 3072);
expect(filter.meta).toHaveProperty('formattedValue');
}

View file

@ -56,12 +56,12 @@ describe('AggConfig Filters', () => {
to: '1.1.1.1',
}) as RangeFilter;
expect(filter).toHaveProperty('range');
expect(filter.query).toHaveProperty('range');
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter.range).toHaveProperty('ip');
expect(filter.range.ip).toHaveProperty('gte', '0.0.0.0');
expect(filter.range.ip).toHaveProperty('lte', '1.1.1.1');
expect(filter.query.range).toHaveProperty('ip');
expect(filter.query.range.ip).toHaveProperty('gte', '0.0.0.0');
expect(filter.query.range.ip).toHaveProperty('lte', '1.1.1.1');
});
test('should return a range filter for ip_range agg using a CIDR mask', () => {
@ -84,12 +84,12 @@ describe('AggConfig Filters', () => {
mask: '67.129.65.201/27',
}) as RangeFilter;
expect(filter).toHaveProperty('range');
expect(filter.query).toHaveProperty('range');
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter.range).toHaveProperty('ip');
expect(filter.range.ip).toHaveProperty('gte', '67.129.65.192');
expect(filter.range.ip).toHaveProperty('lte', '67.129.65.223');
expect(filter.query.range).toHaveProperty('ip');
expect(filter.query.range.ip).toHaveProperty('gte', '67.129.65.192');
expect(filter.query.range.ip).toHaveProperty('lte', '67.129.65.223');
});
});
});

View file

@ -63,13 +63,13 @@ describe('AggConfig Filters', () => {
) as RangeFilter;
expect(mockGetFieldFormatsStart().deserialize).toHaveBeenCalledTimes(1);
expect(filter).toHaveProperty('range');
expect(filter.query).toHaveProperty('range');
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter.range).toHaveProperty('bytes');
expect(filter.range.bytes).toHaveProperty('gte', 1024.0);
expect(filter.range.bytes).toHaveProperty('lt', 2048.0);
expect(filter.range.bytes).not.toHaveProperty('label');
expect(filter.query.range).toHaveProperty('bytes');
expect(filter.query.range.bytes).toHaveProperty('gte', 1024.0);
expect(filter.query.range.bytes).toHaveProperty('lt', 2048.0);
expect(filter.query.range.bytes).not.toHaveProperty('label');
expect(filter.meta).toHaveProperty('formattedValue');
});
});

View file

@ -49,7 +49,7 @@ describe('AggConfig Filters', () => {
expect(filter).toHaveProperty('query');
expect(filter.query).toHaveProperty('match_phrase');
expect(filter.query?.match_phrase).toHaveProperty('field');
expect(filter.query?.match_phrase.field).toBe('apache');
expect(filter.query?.match_phrase?.field).toBe('apache');
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
});
@ -68,7 +68,7 @@ describe('AggConfig Filters', () => {
expect(filterFalse).toHaveProperty('query');
expect(filterFalse.query).toHaveProperty('match_phrase');
expect(filterFalse.query?.match_phrase).toHaveProperty('field');
expect(filterFalse.query?.match_phrase.field).toBeFalsy();
expect(filterFalse.query?.match_phrase?.field).toBeFalsy();
const filterTrue = createFilterTerms(
aggConfigs.aggs[0] as IBucketAggConfig,
@ -79,7 +79,7 @@ describe('AggConfig Filters', () => {
expect(filterTrue).toHaveProperty('query');
expect(filterTrue.query).toHaveProperty('match_phrase');
expect(filterTrue.query?.match_phrase).toHaveProperty('field');
expect(filterTrue.query?.match_phrase.field).toBeTruthy();
expect(filterTrue.query?.match_phrase?.field).toBeTruthy();
});
test('should generate correct __missing__ filter', () => {
@ -92,8 +92,8 @@ describe('AggConfig Filters', () => {
{}
) as ExistsFilter;
expect(filter).toHaveProperty('exists');
expect(filter.exists).toHaveProperty('field', 'field');
expect(filter.query).toHaveProperty('exists');
expect(filter.query.exists).toHaveProperty('field', 'field');
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter.meta).toHaveProperty('negate', true);
@ -111,8 +111,8 @@ describe('AggConfig Filters', () => {
expect(filter).toHaveProperty('query');
expect(filter.query).toHaveProperty('bool');
expect(filter.query?.bool).toHaveProperty('should');
expect(filter.query?.bool.should[0]).toHaveProperty('match_phrase');
expect(filter.query?.bool.should[0].match_phrase).toHaveProperty('field', 'apache');
expect((filter.query?.bool?.should as any)[0]).toHaveProperty('match_phrase');
expect((filter.query?.bool!.should as any)[0].match_phrase).toHaveProperty('field', 'apache');
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter.meta).toHaveProperty('negate', true);

View file

@ -430,8 +430,8 @@ export function insertTimeShiftSplit(
filters[key] = {
range: {
[timeField]: {
gte: moment(timeFilter.range[timeField].gte).subtract(shift).toISOString(),
lte: moment(timeFilter.range[timeField].lte).subtract(shift).toISOString(),
gte: moment(timeFilter.query.range[timeField].gte).subtract(shift).toISOString(),
lte: moment(timeFilter.query.range[timeField].lte).subtract(shift).toISOString(),
},
},
};

View file

@ -93,7 +93,7 @@ describe('createFilter', () => {
if (filters) {
expect(filters.length).toEqual(1);
expect(filters[0].query!.match_phrase.bytes).toEqual('2048');
expect(filters[0].query!.match_phrase!.bytes).toEqual('2048');
}
});
@ -109,8 +109,8 @@ describe('createFilter', () => {
const [rangeFilter] = filters;
if (isRangeFilter(rangeFilter)) {
expect(rangeFilter.range.bytes.gte).toEqual(2048);
expect(rangeFilter.range.bytes.lt).toEqual(2078);
expect(rangeFilter.query.range.bytes.gte).toEqual(2048);
expect(rangeFilter.query.range.bytes.lt).toEqual(2078);
}
}
});

View file

@ -17,15 +17,17 @@ describe('interpreter/functions#existsFilter', () => {
const actual = fn(null, { field: { spec: { name: 'test' } } }, createMockContext());
expect(actual).toMatchInlineSnapshot(`
Object {
"exists": Object {
"field": "test",
},
"meta": Object {
"alias": null,
"disabled": false,
"index": undefined,
"negate": false,
},
"query": Object {
"exists": Object {
"field": "test",
},
},
"type": "kibana_filter",
}
`);

View file

@ -11,11 +11,11 @@ import { filtersToAst } from './filters_to_ast';
describe('interpreter/functions#filtersToAst', () => {
const normalFilter = {
meta: { negate: false, alias: '', disabled: false },
query: { test: 'something' },
query: { query_string: { query: 'something' } },
};
const negatedFilter = {
meta: { negate: true, alias: '', disabled: false },
query: { test: 'something' },
query: { query_string: { query: 'test' } },
};
it('converts a list of filters to an expression AST node', () => {
@ -28,7 +28,7 @@ describe('interpreter/functions#filtersToAst', () => {
expect.objectContaining({
disabled: [false],
negate: [false],
query: ['{"query":{"test":"something"}}'],
query: ['{"query_string":{"query":"something"}}'],
})
);
@ -39,7 +39,7 @@ describe('interpreter/functions#filtersToAst', () => {
expect.objectContaining({
disabled: [false],
negate: [true],
query: ['{"query":{"test":"something"}}'],
query: ['{"query_string":{"query":"test"}}'],
})
);
});

View file

@ -12,12 +12,12 @@ import { ExpressionFunctionKibanaFilter } from './kibana_filter';
export const filtersToAst = (filters: Filter[] | Filter) => {
return (Array.isArray(filters) ? filters : [filters]).map((filter) => {
const { meta, $state, ...restOfFilter } = filter;
const { meta, $state, query, ...restOfFilters } = filter;
return buildExpression([
buildExpressionFunction<ExpressionFunctionKibanaFilter>('kibanaFilter', {
query: JSON.stringify(restOfFilter),
negate: filter.meta.negate,
disabled: filter.meta.disabled,
query: JSON.stringify(query || restOfFilters),
negate: meta.negate,
disabled: meta.disabled,
}),
]).toAst();
});

View file

@ -22,7 +22,9 @@ describe('interpreter/functions#kibanaFilter', () => {
"disabled": false,
"negate": false,
},
"name": "test",
"query": Object {
"name": "test",
},
"type": "kibana_filter",
}
`);

View file

@ -63,7 +63,7 @@ export const kibanaFilterFunction: ExpressionFunctionKibanaFilter = {
alias: '',
disabled: args.disabled || false,
},
...JSON.parse(args.query),
query: JSON.parse(args.query),
};
},
};

View file

@ -29,10 +29,12 @@ describe('interpreter/functions#rangeFilter', () => {
"negate": false,
"params": Object {},
},
"range": Object {
"test": Object {
"gte": 10,
"lt": 20,
"query": Object {
"range": Object {
"test": Object {
"gte": 10,
"lt": 20,
},
},
},
"type": "kibana_filter",

View file

@ -824,7 +824,7 @@ describe('SearchSource', () => {
test('should serialize filters', () => {
const filter = [
{
query: { q: 'query' },
query: { query_string: { query: 'query' } },
meta: {
alias: 'alias',
disabled: false,
@ -842,7 +842,7 @@ describe('SearchSource', () => {
searchSource.setField('index', indexPattern123);
const filter = [
{
query: { q: 'query' },
query: { query_string: { query: 'query' } },
meta: {
alias: 'alias',
disabled: false,
@ -885,7 +885,7 @@ describe('SearchSource', () => {
describe('getSerializedFields', () => {
const filter: Filter[] = [
{
query: { q: 'query' },
query: { query_string: { query: 'query' } },
meta: {
alias: 'alias',
disabled: false,
@ -915,7 +915,9 @@ describe('SearchSource', () => {
"negate": false,
},
"query": Object {
"q": "query",
"query_string": Object {
"query": "query",
},
},
},
],

View file

@ -120,9 +120,11 @@ describe('brushEvent', () => {
if (filter.length) {
const rangeFilter = filter[0] as RangeFilter;
expect(rangeFilter.range.time.gte).toBe(new Date(JAN_01_2014).toISOString());
expect(rangeFilter.query.range.time.gte).toBe(new Date(JAN_01_2014).toISOString());
// Set to a baseline timezone for comparison.
expect(rangeFilter.range.time.lt).toBe(new Date(JAN_01_2014 + DAY_IN_MS).toISOString());
expect(rangeFilter.query.range.time.lt).toBe(
new Date(JAN_01_2014 + DAY_IN_MS).toISOString()
);
}
});
});
@ -150,9 +152,11 @@ describe('brushEvent', () => {
if (filter.length) {
const rangeFilter = filter[0] as RangeFilter;
expect(rangeFilter.range.anotherTimeField.gte).toBe(moment(rangeBegin).toISOString());
expect(rangeFilter.range.anotherTimeField.lt).toBe(moment(rangeEnd).toISOString());
expect(rangeFilter.range.anotherTimeField).toHaveProperty(
expect(rangeFilter.query.range.anotherTimeField.gte).toBe(
moment(rangeBegin).toISOString()
);
expect(rangeFilter.query.range.anotherTimeField.lt).toBe(moment(rangeEnd).toISOString());
expect(rangeFilter.query.range.anotherTimeField).toHaveProperty(
'format',
'strict_date_optional_time'
);
@ -187,9 +191,9 @@ describe('brushEvent', () => {
if (filter.length) {
const rangeFilter = filter[0] as RangeFilter;
expect(rangeFilter.range.numberField.gte).toBe(1);
expect(rangeFilter.range.numberField.lt).toBe(4);
expect(rangeFilter.range.numberField).not.toHaveProperty('format');
expect(rangeFilter.query.range.numberField.gte).toBe(1);
expect(rangeFilter.query.range.numberField.lt).toBe(4);
expect(rangeFilter.query.range.numberField).not.toHaveProperty('format');
}
});
});

View file

@ -86,7 +86,7 @@ describe('createFiltersFromValueClick', () => {
const filters = await createFiltersFromValueClickAction({ data: dataPoints });
expect(filters.length).toEqual(1);
expect(filters[0].query?.match_phrase.bytes).toEqual('2048');
expect(filters[0].query?.match_phrase?.bytes).toEqual('2048');
});
test('handles an event when aggregations type is not terms', async () => {
@ -95,8 +95,8 @@ describe('createFiltersFromValueClick', () => {
expect(filters.length).toEqual(1);
const [rangeFilter] = filters as RangeFilter[];
expect(rangeFilter.range.bytes.gte).toEqual(2048);
expect(rangeFilter.range.bytes.lt).toEqual(2078);
expect(rangeFilter.query.range.bytes.gte).toEqual(2048);
expect(rangeFilter.query.range.bytes.lt).toEqual(2078);
});
test('handles non-unique filters', async () => {

View file

@ -16,7 +16,6 @@ import {
isExistsFilter,
isFilterPinned,
isMatchAllFilter,
isMissingFilter,
isPhraseFilter,
isPhrasesFilter,
isQueryStringFilter,
@ -114,7 +113,6 @@ export const esFilters = {
isPhrasesFilter,
isRangeFilter,
isMatchAllFilter,
isMissingFilter,
isQueryStringFilter,
isFilterPinned,

View file

@ -126,7 +126,7 @@ describe('Generate filters', () => {
expect(filter.meta.index === INDEX_NAME);
expect(filter.meta.negate).toBeFalsy();
expect(isRangeFilter(filter)).toBeTruthy();
expect(filter.range).toEqual({
expect(filter.query.range).toEqual({
[FIELD.name]: {
gt: '192.168.0.0',
lte: '192.168.255.255',

View file

@ -32,7 +32,7 @@ function getExistingFilter(
if (!filter) return;
if (fieldName === '_exists_' && isExistsFilter(filter)) {
return filter.exists!.field === value;
return filter.query.exists!.field === value;
}
if (isPhraseFilter(filter)) {

View file

@ -23,11 +23,11 @@ describe('filter manager utilities', () => {
filters = [
null,
[
{ meta: { index: 'logstash-*' }, exists: { field: '_type' } },
{ meta: { index: 'logstash-*' }, missing: { field: '_type' } },
{ meta: { index: 'logstash-*' }, query: { exists: { field: '_type' } } },
{ meta: { index: 'logstash-*' }, query: { exists: { field: '_type' } } },
],
{ meta: { index: 'logstash-*' }, query: { query_string: { query: 'foo:bar' } } },
{ meta: { index: 'logstash-*' }, range: { bytes: { lt: 2048, gt: 1024 } } },
{ meta: { index: 'logstash-*' }, query: { range: { bytes: { lt: 2048, gt: 1024 } } } },
{
meta: { index: 'logstash-*' },
query: { match: { _type: { query: 'apache', type: 'phrase' } } },
@ -47,7 +47,7 @@ describe('filter manager utilities', () => {
expect(results[0].meta).toHaveProperty('key', '_type');
expect(results[0].meta).toHaveProperty('value', 'exists');
expect(results[1].meta).toHaveProperty('key', '_type');
expect(results[1].meta).toHaveProperty('value', 'missing');
expect(results[1].meta).toHaveProperty('value', 'exists');
expect(results[2].meta).toHaveProperty('key', 'query');
expect(results[2].meta).toHaveProperty('value', 'foo:bar');
expect(results[3].meta).toHaveProperty('key', 'bytes');

View file

@ -7,9 +7,13 @@
*/
import { compact, flatten } from 'lodash';
import { Filter } from '@kbn/es-query';
import { Filter, migrateFilter } from '@kbn/es-query';
import { mapFilter } from './map_filter';
export const mapAndFlattenFilters = (filters: Filter[]) => {
return compact(flatten(filters)).map((item: Filter) => mapFilter(item));
return compact(flatten(filters))
.map((filter) => {
return migrateFilter(filter);
})
.map((item: Filter) => mapFilter(item));
};

View file

@ -33,7 +33,10 @@ describe('filter manager utilities', () => {
});
test('should map exists filters', async () => {
const before: any = { meta: { index: 'logstash-*' }, exists: { field: '@timestamp' } };
const before: any = {
meta: { index: 'logstash-*' },
query: { exists: { field: '@timestamp' } },
};
const after = mapFilter(before as Filter);
expect(after).toHaveProperty('meta');
@ -44,26 +47,14 @@ describe('filter manager utilities', () => {
expect(after.meta).toHaveProperty('negate', false);
});
test('should map missing filters', async () => {
const before: any = { meta: { index: 'logstash-*' }, missing: { field: '@timestamp' } };
const after = mapFilter(before as Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', '@timestamp');
expect(after.meta).toHaveProperty('value');
expect(getDisplayName(after)).toBe('missing');
expect(after.meta).toHaveProperty('disabled', false);
expect(after.meta).toHaveProperty('negate', false);
});
test('should map json filter', async () => {
const before: any = { meta: { index: 'logstash-*' }, query: { match_all: {} } };
const before: any = { meta: { index: 'logstash-*' }, query: { test: {} } };
const after = mapFilter(before as Filter);
expect(after).toHaveProperty('meta');
expect(after.meta).toHaveProperty('key', 'query');
expect(after.meta).toHaveProperty('value');
expect(getDisplayName(after)).toBe('{"match_all":{}}');
expect(getDisplayName(after)).toBe('{"test":{}}');
expect(after.meta).toHaveProperty('disabled', false);
expect(after.meta).toHaveProperty('negate', false);
});

View file

@ -15,7 +15,6 @@ import { mapPhrase } from './mappers/map_phrase';
import { mapPhrases } from './mappers/map_phrases';
import { mapRange } from './mappers/map_range';
import { mapExists } from './mappers/map_exists';
import { mapMissing } from './mappers/map_missing';
import { mapQueryString } from './mappers/map_query_string';
import { mapDefault } from './mappers/map_default';
import { generateMappingChain } from './generate_mapping_chain';
@ -44,7 +43,6 @@ export function mapFilter(filter: Filter) {
mapPhrase,
mapPhrases,
mapExists,
mapMissing,
mapQueryString,
mapDefault,
];

View file

@ -14,7 +14,7 @@ export const mapExists = (filter: Filter) => {
return {
type: FILTERS.EXISTS,
value: FILTERS.EXISTS,
key: get(filter, 'exists.field'),
key: get(filter, 'query.exists.field'),
};
}
throw filter;

View file

@ -15,7 +15,7 @@ describe('filter_manager/lib', () => {
beforeEach(() => {
filter = {
match_all: {},
query: { match_all: {} },
meta: {
alias: null,
negate: true,

View file

@ -1,36 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { mapMissing } from './map_missing';
import { MissingFilter, buildEmptyFilter } from '../../../../../common';
describe('filter manager utilities', () => {
describe('mapMissing()', () => {
test('should return the key and value for matching filters', async () => {
const filter: MissingFilter = {
missing: { field: '_type' },
...buildEmptyFilter(true),
};
const result = mapMissing(filter);
expect(result).toHaveProperty('key', '_type');
expect(result).toHaveProperty('value', 'missing');
});
test('should return undefined for none matching', async (done) => {
const filter = buildEmptyFilter(true);
try {
mapMissing(filter);
} catch (e) {
expect(e).toBe(filter);
done();
}
});
});
});

View file

@ -1,21 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { Filter, isMissingFilter, FILTERS } from '@kbn/es-query';
export const mapMissing = (filter: Filter) => {
if (isMissingFilter(filter)) {
return {
type: FILTERS.MISSING,
value: FILTERS.MISSING,
key: filter.missing.field,
};
}
throw filter;
};

View file

@ -14,7 +14,7 @@ describe('filter manager utilities', () => {
test('should return the key and value for matching filters with gt/lt', async () => {
const filter = {
meta: { index: 'logstash-*' } as FilterMeta,
range: { bytes: { lt: 2048, gt: 1024 } },
query: { range: { bytes: { lt: 2048, gt: 1024 } } },
} as RangeFilter;
const result = mapRange(filter);

View file

@ -22,14 +22,15 @@ const getFormattedValueFn = (left: any, right: any) => {
};
};
const getFirstRangeKey = (filter: RangeFilter) => filter.range && Object.keys(filter.range)[0];
const getRangeByKey = (filter: RangeFilter, key: string) => get(filter, ['range', key]);
const getFirstRangeKey = (filter: RangeFilter) =>
filter.query.range && Object.keys(filter.query.range)[0];
const getRangeByKey = (filter: RangeFilter, key: string) => get(filter.query, ['range', key]);
function getParams(filter: RangeFilter) {
const isScriptedRange = isScriptedRangeFilter(filter);
const key: string = (isScriptedRange ? filter.meta.field : getFirstRangeKey(filter)) || '';
const params: any = isScriptedRange
? get(filter, 'script.script.params')
? get(filter.query, 'script.script.params')
: getRangeByKey(filter, key);
let left = hasIn(params, 'gte') ? params.gte : params.gt;

View file

@ -14,11 +14,11 @@ describe('sortFilters', () => {
test('Not sort two application level filters', () => {
const f1 = {
$state: { store: FilterStateStore.APP_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.APP_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const filters = [f1, f2].sort(sortFilters);
@ -28,11 +28,11 @@ describe('sortFilters', () => {
test('Not sort two global level filters', () => {
const f1 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const filters = [f1, f2].sort(sortFilters);
@ -42,11 +42,11 @@ describe('sortFilters', () => {
test('Move global level filter to the beginning of the array', () => {
const f1 = {
$state: { store: FilterStateStore.APP_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const f2 = {
$state: { store: FilterStateStore.GLOBAL_STATE },
...buildQueryFilter({ _type: { match: { query: 'apache', type: 'phrase' } } }, 'index', ''),
...buildQueryFilter({ query_string: { query: 'apache' } }, 'index', ''),
};
const filters = [f1, f2].sort(sortFilters);

View file

@ -11,15 +11,15 @@ import { Filter } from '../../../../common';
export function getFiltersArray(): Filter[] {
return [
{
query: { match: { extension: { query: 'jpg', type: 'phrase' } } },
query: { match: { extension: { query: 'jpg' } } },
meta: { index: 'logstash-*', negate: false, disabled: false, alias: null },
},
{
query: { match: { '@tags': { query: 'info', type: 'phrase' } } },
query: { match: { '@tags': { query: 'info' } } },
meta: { index: 'logstash-*', negate: false, disabled: false, alias: null },
},
{
query: { match: { _type: { query: 'nginx', type: 'phrase' } } },
query: { match: { _type: { query: 'nginx' } } },
meta: { index: 'logstash-*', negate: false, disabled: false, alias: null },
},
];

View file

@ -30,7 +30,7 @@ describe('changeTimeFilter()', () => {
const lt = 1388646000000;
test('should change the timefilter to match the range gt/lt', () => {
const filter: any = { range: { '@timestamp': { gt, lt } } };
const filter: any = { query: { range: { '@timestamp': { gt, lt } } } };
changeTimeFilter(timefilter, filter as RangeFilter);
const { to, from } = timefilter.getTime();
@ -40,7 +40,7 @@ describe('changeTimeFilter()', () => {
});
test('should change the timefilter to match the range gte/lte', () => {
const filter: any = { range: { '@timestamp': { gte: gt, lte: lt } } };
const filter: any = { query: { range: { '@timestamp': { gte: gt, lte: lt } } } };
changeTimeFilter(timefilter, filter as RangeFilter);
const { to, from } = timefilter.getTime();

View file

@ -13,8 +13,8 @@ import { TimefilterContract } from '../../timefilter';
import { TimeRange } from '../../../../common';
export function convertRangeFilterToTimeRange(filter: RangeFilter) {
const key = keys(filter.range)[0];
const values = filter.range[key];
const key = keys(filter.query.range)[0];
const values = filter.query.range[key];
return {
from: moment(values.gt || values.gte),

View file

@ -28,11 +28,7 @@ describe('filter manager utilities', () => {
describe('extractTimeFilter()', () => {
test('should detect timeFilter', async () => {
const filters: Filter[] = [
buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'logstash-*',
''
),
buildQueryFilter({ query_string: { query: 'apache' } }, 'logstash-*', ''),
buildRangeFilter(
{ name: 'time' } as IFieldType,
{ gt: 1388559600000, lt: 1388646000000 },
@ -47,11 +43,7 @@ describe('filter manager utilities', () => {
test("should not return timeFilter when name doesn't match", async () => {
const filters: Filter[] = [
buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'logstash-*',
''
),
buildQueryFilter({ query_string: { query: 'apache' } }, 'logstash-*', ''),
buildRangeFilter(
{ name: '@timestamp' } as IFieldType,
{ from: 1, to: 2 },
@ -67,11 +59,7 @@ describe('filter manager utilities', () => {
test('should not return a non range filter, even when names match', async () => {
const filters: Filter[] = [
buildQueryFilter(
{ _type: { match: { query: 'apache', type: 'phrase' } } },
'logstash-*',
''
),
buildQueryFilter({ query_string: { query: 'apache' } }, 'logstash-*', ''),
buildPhraseFilter({ name: 'time' } as IFieldType, 'banana', indexPattern),
];
const result = await extractTimeFilter('time', filters);

View file

@ -16,7 +16,7 @@ export function extractTimeFilter(timeFieldName: string, filters: Filter[]) {
let key;
if (isRangeFilter(obj)) {
key = keys(obj.range)[0];
key = keys(obj.query.range)[0];
}
return Boolean(key && key === timeFieldName);

View file

@ -148,10 +148,9 @@ describe('Test Discover Context State', () => {
"value": [Function],
},
"query": Object {
"match": Object {
"match_phrase": Object {
"extension": Object {
"query": "jpg",
"type": "phrase",
},
},
},
@ -173,10 +172,9 @@ describe('Test Discover Context State', () => {
"value": [Function],
},
"query": Object {
"match": Object {
"match_phrase": Object {
"extension": Object {
"query": "png",
"type": "phrase",
},
},
},
@ -185,7 +183,7 @@ describe('Test Discover Context State', () => {
`);
state.flushToUrl();
expect(getCurrentUrl()).toMatchInlineSnapshot(
`"/#?_g=(filters:!(('$state':(store:globalState),meta:(alias:!n,disabled:!f,index:'logstash-*',key:extension,negate:!f,params:(query:jpg),type:phrase),query:(match:(extension:(query:jpg,type:phrase))))))&_a=(columns:!(_source),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'logstash-*',key:extension,negate:!t,params:(query:png),type:phrase),query:(match:(extension:(query:png,type:phrase))))),predecessorCount:4,sort:!(!(time,desc)),successorCount:4)"`
`"/#?_g=(filters:!(('$state':(store:globalState),meta:(alias:!n,disabled:!f,index:'logstash-*',key:extension,negate:!f,params:(query:jpg),type:phrase),query:(match_phrase:(extension:(query:jpg))))))&_a=(columns:!(_source),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'logstash-*',key:extension,negate:!t,params:(query:png),type:phrase),query:(match_phrase:(extension:(query:png))))),predecessorCount:4,sort:!(!(time,desc)),successorCount:4)"`
);
});
});

View file

@ -57,8 +57,8 @@ describe('RangeFilterManager', function () {
expect(newFilter.meta.index).to.be(indexPatternId);
expect(newFilter.meta.controlledBy).to.be(controlId);
expect(newFilter.meta.key).to.be('field1');
expect(newFilter).to.have.property('range');
expect(JSON.stringify(newFilter.range, null, '')).to.be('{"field1":{"gte":1,"lte":3}}');
expect(newFilter.query).to.have.property('range');
expect(JSON.stringify(newFilter.query.range, null, '')).to.be('{"field1":{"gte":1,"lte":3}}');
});
});
@ -102,10 +102,12 @@ describe('RangeFilterManager', function () {
test('should extract value from range filter', function () {
filterManager.setMockFilters([
{
range: {
field1: {
gt: 1,
lt: 3,
query: {
range: {
field1: {
gt: 1,
lt: 3,
},
},
},
meta: {} as RangeFilterMeta,
@ -122,10 +124,12 @@ describe('RangeFilterManager', function () {
test('should return undefined when filter value can not be extracted from Kibana filter', function () {
filterManager.setMockFilters([
{
range: {
myFieldWhichIsNotField1: {
gte: 1,
lte: 3,
query: {
range: {
myFieldWhichIsNotField1: {
gte: 1,
lte: 3,
},
},
},
meta: {} as RangeFilterMeta,

View file

@ -68,10 +68,10 @@ export class RangeFilterManager extends FilterManager {
}
let range: RangeFilterParams;
if (_.has(kbnFilters[0], 'script')) {
range = _.get(kbnFilters[0], 'script.script.params');
if (_.has(kbnFilters[0], 'query.script')) {
range = _.get(kbnFilters[0], 'query.script.script.params');
} else {
range = _.get(kbnFilters[0], ['range', this.fieldName]);
range = _.get(kbnFilters[0], ['query', 'range', this.fieldName]);
}
if (!range) {

View file

@ -124,14 +124,16 @@ describe('query', () => {
test('returns doc with global query', async () => {
req.body.filters = [
{
bool: {
must: [
{
term: {
host: 'example',
query: {
bool: {
must: [
{
term: {
host: 'example',
},
},
},
],
],
},
},
},
];
@ -234,14 +236,16 @@ describe('query', () => {
test('returns doc with panel filter and global', async () => {
req.body.filters = [
{
bool: {
must: [
{
term: {
host: 'example',
query: {
bool: {
must: [
{
term: {
host: 'example',
},
},
},
],
],
},
},
},
];

View file

@ -12,17 +12,19 @@ const body = JSON.parse(`
{
"filters": [
{
"bool": {
"must": [
{
"query_string": {
"analyze_wildcard": true,
"query": "*"
}
}
],
"must_not": []
}
"query": {
"bool": {
"must": [
{
"query_string": {
"analyze_wildcard": true,
"query": "*"
}
}
],
"must_not": []
}
}
}
],
"panels": [

View file

@ -358,11 +358,13 @@ export class VegaBaseView {
timeFieldName: '*',
filters: [
{
range: {
'*': {
mode,
gte: from,
lte: to,
query: {
range: {
'*': {
mode,
gte: from,
lte: to,
},
},
},
},

View file

@ -84,8 +84,10 @@ const existFilter: Filter = {
key: 'transaction.marks.navigationTiming.fetchStart',
value: 'exists',
},
exists: {
field: 'transaction.marks.navigationTiming.fetchStart',
query: {
exists: {
field: 'transaction.marks.navigationTiming.fetchStart',
},
},
};
@ -108,7 +110,7 @@ export const useMapFilters = (): Filter[] => {
} = uxUiFilters;
return useMemo(() => {
const filters = [existFilter];
const filters: Filter[] = [existFilter];
if (serviceName) {
filters.push(getMatchFilter(SERVICE_NAME, serviceName));
}

View file

@ -349,11 +349,13 @@ function getMockTimeRangeFilter(): RangeFilter {
negate: false,
alias: null,
},
range: {
order_date: {
gte: '2020-03-23T13:10:29.665Z',
lt: '2020-03-23T13:10:36.736Z',
format: 'strict_date_optional_time',
query: {
range: {
order_date: {
gte: '2020-03-23T13:10:29.665Z',
lt: '2020-03-23T13:10:36.736Z',
format: 'strict_date_optional_time',
},
},
},
};

View file

@ -234,10 +234,12 @@ describe('"Explore underlying data" panel action', () => {
lte: to,
},
},
range: {
[timeFieldName]: {
gte: from,
lte: to,
query: {
range: {
[timeFieldName]: {
gte: from,
lte: to,
},
},
},
},

View file

@ -215,7 +215,7 @@ describe('IndexPattern Field Item', () => {
query: { query: 'geo.src : "US"', language: 'kuery' },
filters: [
{
match: { phrase: { 'geo.dest': 'US' } },
query: { match: { phrase: { 'geo.dest': 'US' } } },
},
],
});

View file

@ -125,8 +125,10 @@ describe('getESFilters', () => {
index: 'indexPatternId',
negate: true,
},
exists: {
field: 'machine.os',
query: {
exists: {
field: 'machine.os',
},
},
},
]);

View file

@ -505,7 +505,7 @@ export class LensAttributes {
const existFilter = filter as ExistsFilter;
if (isExistsFilter(existFilter)) {
const fieldName = existFilter.exists?.field;
const fieldName = existFilter.query.exists?.field;
const kql = `${fieldName} : *`;
if (baseFilters.length > 0) {
baseFilters += ` and ${kql}`;

View file

@ -66,7 +66,7 @@ export function FilterExpanded({
queryFilters.push(qFilter.query);
}
if (isExistsFilter(qFilter)) {
queryFilters.push({ exists: qFilter.exists } as QueryDslQueryContainer);
queryFilters.push({ exists: qFilter.query.exists } as QueryDslQueryContainer);
}
});

View file

@ -38,8 +38,8 @@ export function ReportDefinitionField({ series, field, seriesConfig, onChange }:
filtersN.push(qFilter.query);
}
const existFilter = qFilter as ExistsFilter;
if (existFilter.exists) {
filtersN.push({ exists: existFilter.exists });
if (existFilter.query.exists) {
filtersN.push({ exists: existFilter.query.exists });
}
});

View file

@ -395,7 +395,7 @@ export class AlertsClient {
esQuery == null ? { query: ``, language: 'kuery' } : esQuery,
[
authzFilter as unknown as Filter,
{ term: { [SPACE_IDS]: alertSpaceId } } as unknown as Filter,
{ query: { term: { [SPACE_IDS]: alertSpaceId } } } as unknown as Filter,
],
config
);

View file

@ -216,8 +216,10 @@ describe('get_filter', () => {
};
const exists: Partial<Filter> = {
exists: {
field: 'host.hostname',
query: {
exists: {
field: 'host.hostname',
},
},
} as Partial<Filter>;

View file

@ -65,10 +65,9 @@ const state: State = {
},
},
query: {
match: {
match_phrase: {
'host.os.name': {
query: 'Linux',
type: 'phrase',
},
},
},
@ -121,10 +120,9 @@ const state: State = {
type: 'phrase',
},
query: {
match: {
match_phrase: {
'source.port': {
query: '30045',
type: 'phrase',
},
},
},
@ -256,7 +254,7 @@ describe('StatefulTopN', () => {
key: 'host.os.name',
params: { query: 'Linux' },
},
query: { match: { 'host.os.name': { query: 'Linux', type: 'phrase' } } },
query: { match_phrase: { 'host.os.name': { query: 'Linux' } } },
},
]);
});

View file

@ -52,8 +52,10 @@ describe('alerts default_config', () => {
type: 'exists',
value: 'exists',
},
exists: {
field: 'signal.rule.threat_mapping',
query: {
exists: {
field: 'signal.rule.threat_mapping',
},
},
};
expect(filters).toHaveLength(1);

View file

@ -130,8 +130,7 @@ export const buildShowBuildingBlockFilter = (showBuildingBlockAlerts: boolean):
key: 'signal.rule.building_block_type',
value: 'exists',
},
// @ts-expect-error TODO: Rework parent typings to support ExistsFilter[]
exists: { field: 'signal.rule.building_block_type' },
query: { exists: { field: 'signal.rule.building_block_type' } },
},
];
@ -147,8 +146,7 @@ export const buildThreatMatchFilter = (showOnlyThreatIndicatorAlerts: boolean):
type: 'exists',
value: 'exists',
},
// @ts-expect-error TODO: Rework parent typings to support ExistsFilter[]
exists: { field: 'signal.rule.threat_mapping' },
query: { exists: { field: 'signal.rule.threat_mapping' } },
},
]
: [];
@ -268,8 +266,7 @@ export const buildShowBuildingBlockFilterRuleRegistry = (
key: 'kibana.rule.building_block_type',
value: 'exists',
},
// @ts-expect-error TODO: Rework parent typings to support ExistsFilter[]
exists: { field: 'kibana.rule.building_block_type' },
query: { exists: { field: 'kibana.rule.building_block_type' } },
},
];

View file

@ -98,7 +98,7 @@ describe('query_preview/helpers', () => {
expect(queryString).toEqual('host.name:*');
expect(language).toEqual('kuery');
expect(filters).toEqual([{ meta: { alias: '', disabled: false, negate: false } }]);
expect(filters).toEqual([{ meta: { alias: '', disabled: false, negate: false }, query: {} }]);
expect(queryFilter).toEqual({
bool: {
filter: [
@ -124,7 +124,7 @@ describe('query_preview/helpers', () => {
expect(queryString).toEqual('host.name:*');
expect(language).toEqual('kuery');
expect(filters).toEqual([{ meta: { alias: '', disabled: false, negate: false } }]);
expect(filters).toEqual([{ meta: { alias: '', disabled: false, negate: false }, query: {} }]);
expect(queryFilter).toEqual({
bool: {
filter: [
@ -150,7 +150,7 @@ describe('query_preview/helpers', () => {
expect(queryString).toEqual('host.name:*');
expect(language).toEqual('kuery');
expect(filters).toEqual([{ meta: { alias: '', disabled: false, negate: false } }]);
expect(filters).toEqual([{ meta: { alias: '', disabled: false, negate: false }, query: {} }]);
expect(queryFilter).toEqual({
bool: {
filter: [

View file

@ -79,7 +79,9 @@ describe('queryPreviewReducer', () => {
expect(update.language).toEqual('kuery');
expect(update.queryString).toEqual('host.name:*');
expect(update.filters).toEqual([{ meta: { alias: '', disabled: false, negate: false } }]);
expect(update.filters).toEqual([
{ meta: { alias: '', disabled: false, negate: false }, query: {} },
]);
});
test('should create the queryFilter if query type is not eql', () => {

View file

@ -290,7 +290,7 @@ describe('Combined Queries', () => {
type: 'exists',
value: 'exists',
},
exists: { field: 'host.name' },
query: { exists: { field: 'host.name' } },
} as Filter,
],
kqlQuery: { query: '', language: 'kuery' },
@ -515,8 +515,10 @@ describe('Combined Queries', () => {
key: 'nestedField.firstAttributes',
value: 'exists',
},
exists: {
field: 'nestedField.firstAttributes',
query: {
exists: {
field: 'nestedField.firstAttributes',
},
},
$state: {
store: esFilters.FilterStateStore.APP_STATE,

View file

@ -126,7 +126,7 @@ describe('Epic Timeline', () => {
type: 'exists',
value: 'exists',
},
exists: { field: '@timestamp' },
query: { exists: { field: '@timestamp' } },
} as Filter,
],
indexNames: [],
@ -264,13 +264,12 @@ describe('Epic Timeline', () => {
type: 'phrase',
value: null,
},
missing: null,
query: '{"match_phrase":{"event.category":"file"}}',
range: null,
script: null,
},
{
exists: '{"field":"@timestamp"}',
query: '{"exists":{"field":"@timestamp"}}',
match_all: null,
meta: {
alias: null,
@ -282,8 +281,6 @@ describe('Epic Timeline', () => {
type: 'exists',
value: 'exists',
},
missing: null,
query: null,
range: null,
script: null,
},

View file

@ -392,27 +392,28 @@ export const convertTimelineAsInput = (
},
...(esFilters.isMatchAllFilter(basicFilter)
? {
match_all: convertToString((basicFilter as MatchAllFilter).match_all),
query: {
match_all: convertToString(
(basicFilter as MatchAllFilter).query.match_all
),
},
}
: { match_all: null }),
...(esFilters.isMissingFilter(basicFilter) && basicFilter.missing != null
? { missing: convertToString(basicFilter.missing) }
: { missing: null }),
...(esFilters.isExistsFilter(basicFilter) && basicFilter.exists != null
? { exists: convertToString(basicFilter.exists) }
...(esFilters.isExistsFilter(basicFilter) && basicFilter.query.exists != null
? { query: { exists: convertToString(basicFilter.query.exists) } }
: { exists: null }),
...((esFilters.isQueryStringFilter(basicFilter) ||
get('query', basicFilter) != null) &&
basicFilter.query != null
? { query: convertToString(basicFilter.query) }
: { query: null }),
...(esFilters.isRangeFilter(basicFilter) && basicFilter.range != null
? { range: convertToString(basicFilter.range) }
...(esFilters.isRangeFilter(basicFilter) && basicFilter.query.range != null
? { query: { range: convertToString(basicFilter.query.range) } }
: { range: null }),
...(isScriptedRangeFilter(basicFilter) &&
basicFilter.script !=
basicFilter.query.script !=
null /* TODO remove it when PR50713 is merged || esFilters.isPhraseFilter(basicFilter) */
? { script: convertToString(basicFilter.script) }
? { query: { script: convertToString(basicFilter.query.script) } }
: { script: null }),
};
})

View file

@ -288,7 +288,7 @@ describe('Combined Queries', () => {
type: 'exists',
value: 'exists',
},
exists: { field: 'host.name' },
query: { exists: { field: 'host.name' } },
} as Filter,
],
kqlQuery: { query: '', language: 'kuery' },
@ -489,8 +489,10 @@ describe('Combined Queries', () => {
key: 'nestedField.firstAttributes',
value: 'exists',
},
exists: {
field: 'nestedField.firstAttributes',
query: {
exists: {
field: 'nestedField.firstAttributes',
},
},
$state: {
store: esFilters.FilterStateStore.APP_STATE,

View file

@ -120,7 +120,7 @@ export default function ({ getPageObjects, getService }) {
const currentUrl = await browser.getCurrentUrl();
const appState = currentUrl.substring(currentUrl.indexOf('_a='));
expect(appState).to.equal(
'_a=(filters:!((%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,index:c698b940-e149-11e8-a35a-370a8516603a,key:machine.os.raw,negate:!f,params:(query:ios),type:phrase),query:(match:(machine.os.raw:(query:ios,type:phrase))))),query:(language:kuery,query:%27%27))'
'_a=(filters:!((%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,index:c698b940-e149-11e8-a35a-370a8516603a,key:machine.os.raw,negate:!f,params:(query:ios),type:phrase),query:(match_phrase:(machine.os.raw:(query:ios))))),query:(language:kuery,query:%27%27))'
);
});