mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[expressions] select_filter and remove_filter functions (#113533)
This commit is contained in:
parent
933ece47ad
commit
800cfb504c
8 changed files with 579 additions and 0 deletions
|
@ -56,6 +56,8 @@ export type FilterMeta = {
|
|||
negate?: boolean;
|
||||
// controlledBy is there to identify who owns the filter
|
||||
controlledBy?: string;
|
||||
// allows grouping of filters
|
||||
group?: string;
|
||||
// index and type are optional only because when you create a new filter, there are no defaults
|
||||
index?: string;
|
||||
isMultiIndex?: boolean;
|
||||
|
|
|
@ -36,6 +36,8 @@ export * from './field';
|
|||
export * from './phrase_filter';
|
||||
export * from './exists_filter';
|
||||
export * from './range_filter';
|
||||
export * from './remove_filter';
|
||||
export * from './select_filter';
|
||||
export * from './kibana_filter';
|
||||
export * from './filters_to_ast';
|
||||
export * from './timerange';
|
||||
|
|
206
src/plugins/data/common/search/expressions/remove_filter.test.ts
Normal file
206
src/plugins/data/common/search/expressions/remove_filter.test.ts
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* 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 { createMockContext } from '../../../../expressions/common';
|
||||
import { functionWrapper } from './utils';
|
||||
import { removeFilterFunction } from './remove_filter';
|
||||
import { KibanaContext } from './kibana_context_type';
|
||||
|
||||
describe('interpreter/functions#removeFilter', () => {
|
||||
const fn = functionWrapper(removeFilterFunction);
|
||||
const kibanaContext: KibanaContext = {
|
||||
type: 'kibana_context',
|
||||
filters: [
|
||||
{
|
||||
meta: {
|
||||
group: 'g1',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
group: 'g2',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
group: 'g1',
|
||||
controlledBy: 'i1',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
group: 'g1',
|
||||
controlledBy: 'i2',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
controlledBy: 'i1',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
it('removes all filters when called without arguments', () => {
|
||||
const actual = fn(kibanaContext, {}, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('removes filters belonging to certain group', () => {
|
||||
const actual = fn(kibanaContext, { group: 'g1' }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g2",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('removes ungrouped filters', () => {
|
||||
const actual = fn(kibanaContext, { ungrouped: true }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g2",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i2",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('removes ungrouped filters and filters matching a group', () => {
|
||||
const actual = fn(kibanaContext, { group: 'g1', ungrouped: true }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g2",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('removes filters controlled by specified id', () => {
|
||||
const actual = fn(kibanaContext, { from: 'i1' }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g2",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i2",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('removes filters controlled by specified id and matching a group', () => {
|
||||
const actual = fn(kibanaContext, { group: 'g1', from: 'i1' }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g2",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i2",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
69
src/plugins/data/common/search/expressions/remove_filter.ts
Normal file
69
src/plugins/data/common/search/expressions/remove_filter.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
|
||||
import { KibanaContext } from './kibana_context_type';
|
||||
|
||||
interface Arguments {
|
||||
group?: string;
|
||||
from?: string;
|
||||
ungrouped?: boolean;
|
||||
}
|
||||
|
||||
export type ExpressionFunctionRemoveFilter = ExpressionFunctionDefinition<
|
||||
'removeFilter',
|
||||
KibanaContext,
|
||||
Arguments,
|
||||
KibanaContext
|
||||
>;
|
||||
|
||||
export const removeFilterFunction: ExpressionFunctionRemoveFilter = {
|
||||
name: 'removeFilter',
|
||||
type: 'kibana_context',
|
||||
inputTypes: ['kibana_context'],
|
||||
help: i18n.translate('data.search.functions.removeFilter.help', {
|
||||
defaultMessage: 'Removes filters from context',
|
||||
}),
|
||||
args: {
|
||||
group: {
|
||||
types: ['string'],
|
||||
aliases: ['_'],
|
||||
help: i18n.translate('data.search.functions.removeFilter.group.help', {
|
||||
defaultMessage: 'Removes only filters belonging to the provided group',
|
||||
}),
|
||||
},
|
||||
from: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('data.search.functions.removeFilter.from.help', {
|
||||
defaultMessage: 'Removes only filters owned by the provided id',
|
||||
}),
|
||||
},
|
||||
ungrouped: {
|
||||
types: ['boolean'],
|
||||
aliases: ['nogroup', 'nogroups'],
|
||||
default: false,
|
||||
help: i18n.translate('data.search.functions.removeFilter.ungrouped.help', {
|
||||
defaultMessage: 'Should filters without group be removed',
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
fn(input, { group, from, ungrouped }) {
|
||||
return {
|
||||
...input,
|
||||
filters:
|
||||
input.filters?.filter(({ meta }) => {
|
||||
const isGroupMatching =
|
||||
(!group && !ungrouped) || group === meta.group || (ungrouped && !meta.group);
|
||||
const isOriginMatching = !from || from === meta.controlledBy;
|
||||
return !isGroupMatching || !isOriginMatching;
|
||||
}) || [],
|
||||
};
|
||||
},
|
||||
};
|
223
src/plugins/data/common/search/expressions/select_filter.test.ts
Normal file
223
src/plugins/data/common/search/expressions/select_filter.test.ts
Normal file
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* 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 { createMockContext } from '../../../../expressions/common';
|
||||
import { functionWrapper } from './utils';
|
||||
import { selectFilterFunction } from './select_filter';
|
||||
import { KibanaContext } from './kibana_context_type';
|
||||
|
||||
describe('interpreter/functions#selectFilter', () => {
|
||||
const fn = functionWrapper(selectFilterFunction);
|
||||
const kibanaContext: KibanaContext = {
|
||||
type: 'kibana_context',
|
||||
filters: [
|
||||
{
|
||||
meta: {
|
||||
group: 'g1',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
group: 'g2',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
group: 'g1',
|
||||
controlledBy: 'i1',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
group: 'g1',
|
||||
controlledBy: 'i2',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
controlledBy: 'i1',
|
||||
},
|
||||
query: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
it('selects all filters when called without arguments', () => {
|
||||
const actual = fn(kibanaContext, {}, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g2",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i2",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('selects filters belonging to certain group', () => {
|
||||
const actual = fn(kibanaContext, { group: 'g1' }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i2",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('selects ungrouped filters', () => {
|
||||
const actual = fn(kibanaContext, { ungrouped: true }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('selects ungrouped filters and filters matching a group', () => {
|
||||
const actual = fn(kibanaContext, { group: 'g1', ungrouped: true }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i2",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('selects filters controlled by specified id', () => {
|
||||
const actual = fn(kibanaContext, { from: 'i1' }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('selects filters controlled by specified id and matching a group', () => {
|
||||
const actual = fn(kibanaContext, { group: 'g1', from: 'i1' }, createMockContext());
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"filters": Array [
|
||||
Object {
|
||||
"meta": Object {
|
||||
"controlledBy": "i1",
|
||||
"group": "g1",
|
||||
},
|
||||
"query": Object {},
|
||||
},
|
||||
],
|
||||
"type": "kibana_context",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
69
src/plugins/data/common/search/expressions/select_filter.ts
Normal file
69
src/plugins/data/common/search/expressions/select_filter.ts
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
|
||||
import { KibanaContext } from './kibana_context_type';
|
||||
|
||||
interface Arguments {
|
||||
group?: string;
|
||||
from?: string;
|
||||
ungrouped?: boolean;
|
||||
}
|
||||
|
||||
export type ExpressionFunctionSelectFilter = ExpressionFunctionDefinition<
|
||||
'selectFilter',
|
||||
KibanaContext,
|
||||
Arguments,
|
||||
KibanaContext
|
||||
>;
|
||||
|
||||
export const selectFilterFunction: ExpressionFunctionSelectFilter = {
|
||||
name: 'selectFilter',
|
||||
type: 'kibana_context',
|
||||
inputTypes: ['kibana_context'],
|
||||
help: i18n.translate('data.search.functions.selectFilter.help', {
|
||||
defaultMessage: 'Selects filters from context',
|
||||
}),
|
||||
args: {
|
||||
group: {
|
||||
types: ['string'],
|
||||
aliases: ['_'],
|
||||
help: i18n.translate('data.search.functions.selectFilter.group.help', {
|
||||
defaultMessage: 'Select only filters belonging to the provided group',
|
||||
}),
|
||||
},
|
||||
from: {
|
||||
types: ['string'],
|
||||
help: i18n.translate('data.search.functions.selectFilter.from.help', {
|
||||
defaultMessage: 'Select only filters owned by the provided id',
|
||||
}),
|
||||
},
|
||||
ungrouped: {
|
||||
types: ['boolean'],
|
||||
aliases: ['nogroup', 'nogroups'],
|
||||
default: false,
|
||||
help: i18n.translate('data.search.functions.selectFilter.ungrouped.help', {
|
||||
defaultMessage: 'Should filters without group be included',
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
fn(input, { group, ungrouped, from }) {
|
||||
return {
|
||||
...input,
|
||||
filters:
|
||||
input.filters?.filter(({ meta }) => {
|
||||
const isGroupMatching =
|
||||
(!group && !ungrouped) || group === meta.group || (ungrouped && !meta.group);
|
||||
const isOriginMatching = !from || from === meta.controlledBy;
|
||||
return isGroupMatching && isOriginMatching;
|
||||
}) || [],
|
||||
};
|
||||
},
|
||||
};
|
|
@ -39,6 +39,8 @@ import {
|
|||
geoPointFunction,
|
||||
queryFilterFunction,
|
||||
rangeFilterFunction,
|
||||
removeFilterFunction,
|
||||
selectFilterFunction,
|
||||
kibanaFilterFunction,
|
||||
phraseFilterFunction,
|
||||
esRawResponse,
|
||||
|
@ -139,6 +141,8 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
expressions.registerFunction(existsFilterFunction);
|
||||
expressions.registerFunction(queryFilterFunction);
|
||||
expressions.registerFunction(rangeFilterFunction);
|
||||
expressions.registerFunction(removeFilterFunction);
|
||||
expressions.registerFunction(selectFilterFunction);
|
||||
expressions.registerFunction(phraseFilterFunction);
|
||||
expressions.registerType(kibanaContext);
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@ import {
|
|||
numericalRangeFunction,
|
||||
queryFilterFunction,
|
||||
rangeFilterFunction,
|
||||
removeFilterFunction,
|
||||
selectFilterFunction,
|
||||
rangeFunction,
|
||||
SearchSourceDependencies,
|
||||
searchSourceRequiredUiSettings,
|
||||
|
@ -205,6 +207,8 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
expressions.registerFunction(existsFilterFunction);
|
||||
expressions.registerFunction(queryFilterFunction);
|
||||
expressions.registerFunction(rangeFilterFunction);
|
||||
expressions.registerFunction(removeFilterFunction);
|
||||
expressions.registerFunction(selectFilterFunction);
|
||||
expressions.registerFunction(phraseFilterFunction);
|
||||
expressions.registerType(kibanaContext);
|
||||
expressions.registerType(esRawResponse);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue