Skip to content

Commit 84c9662

Browse files
[ML] Fix new job with must_not saved search (#71831)
* [ML] Fix new job with must_not saved search * adding tests * initialising saved search in beforeEach * another commit for odd github issues Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent 755f9f4 commit 84c9662

File tree

2 files changed

+217
-4
lines changed

2 files changed

+217
-4
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { IUiSettingsClient } from 'kibana/public';
8+
import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns';
9+
import { SavedSearchSavedObject } from '../../../../../common/types/kibana';
10+
import { createSearchItems } from './new_job_utils';
11+
12+
describe('createSearchItems', () => {
13+
const kibanaConfig = {} as IUiSettingsClient;
14+
const indexPattern = ({
15+
fields: [],
16+
} as unknown) as IIndexPattern;
17+
18+
let savedSearch = ({} as unknown) as SavedSearchSavedObject;
19+
beforeEach(() => {
20+
savedSearch = ({
21+
client: {
22+
http: {
23+
basePath: {
24+
basePath: '/abc',
25+
serverBasePath: '/abc',
26+
},
27+
anonymousPaths: {},
28+
},
29+
batchQueue: [],
30+
},
31+
attributes: {
32+
title: 'not test',
33+
description: '',
34+
hits: 0,
35+
columns: ['_source'],
36+
sort: [],
37+
version: 1,
38+
kibanaSavedObjectMeta: {
39+
searchSourceJSON: '',
40+
},
41+
},
42+
_version: 'WzI0OSw0XQ==',
43+
id: '4b9b1010-c678-11ea-b6e6-e942978da29c',
44+
type: 'search',
45+
migrationVersion: {
46+
search: '7.4.0',
47+
},
48+
references: [
49+
{
50+
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
51+
type: 'index-pattern',
52+
id: '7e252840-bd27-11ea-8a6c-75d1a0bd08ab',
53+
},
54+
],
55+
} as unknown) as SavedSearchSavedObject;
56+
});
57+
58+
test('should match index pattern', () => {
59+
const resp = createSearchItems(kibanaConfig, indexPattern, null);
60+
expect(resp).toStrictEqual({
61+
combinedQuery: { bool: { must: [{ match_all: {} }] } },
62+
query: { query: '', language: 'lucene' },
63+
});
64+
});
65+
66+
test('should match saved search with kuery and condition', () => {
67+
const searchSource = {
68+
highlightAll: true,
69+
version: true,
70+
query: { query: 'airline : "AAL" ', language: 'kuery' },
71+
filter: [],
72+
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
73+
};
74+
savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify(searchSource);
75+
76+
const resp = createSearchItems(kibanaConfig, indexPattern, savedSearch);
77+
expect(resp).toStrictEqual({
78+
combinedQuery: {
79+
bool: {
80+
should: [{ match_phrase: { airline: 'AAL' } }],
81+
minimum_should_match: 1,
82+
filter: [],
83+
must_not: [],
84+
},
85+
},
86+
query: {
87+
language: 'kuery',
88+
query: 'airline : "AAL" ',
89+
},
90+
});
91+
});
92+
93+
test('should match saved search with kuery and not condition', () => {
94+
const searchSource = {
95+
highlightAll: true,
96+
version: true,
97+
query: { query: 'NOT airline : "AAL" ', language: 'kuery' },
98+
filter: [],
99+
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
100+
};
101+
savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify(searchSource);
102+
103+
const resp = createSearchItems(kibanaConfig, indexPattern, savedSearch);
104+
expect(resp).toStrictEqual({
105+
combinedQuery: {
106+
bool: {
107+
filter: [],
108+
must_not: [
109+
{
110+
bool: {
111+
minimum_should_match: 1,
112+
should: [
113+
{
114+
match_phrase: {
115+
airline: 'AAL',
116+
},
117+
},
118+
],
119+
},
120+
},
121+
],
122+
},
123+
},
124+
query: {
125+
language: 'kuery',
126+
query: 'NOT airline : "AAL" ',
127+
},
128+
});
129+
});
130+
131+
test('should match saved search with kuery and condition and not condition', () => {
132+
const searchSource = {
133+
highlightAll: true,
134+
version: true,
135+
query: { query: 'airline : "AAL" and NOT airline : "AWE" ', language: 'kuery' },
136+
filter: [],
137+
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
138+
};
139+
savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify(searchSource);
140+
141+
const resp = createSearchItems(kibanaConfig, indexPattern, savedSearch);
142+
expect(resp).toStrictEqual({
143+
combinedQuery: {
144+
bool: {
145+
filter: [
146+
{ bool: { should: [{ match_phrase: { airline: 'AAL' } }], minimum_should_match: 1 } },
147+
{
148+
bool: {
149+
must_not: {
150+
bool: { should: [{ match_phrase: { airline: 'AWE' } }], minimum_should_match: 1 },
151+
},
152+
},
153+
},
154+
],
155+
must_not: [],
156+
},
157+
},
158+
query: { query: 'airline : "AAL" and NOT airline : "AWE" ', language: 'kuery' },
159+
});
160+
});
161+
162+
test('should match saved search with kuery and filter', () => {
163+
const searchSource = {
164+
highlightAll: true,
165+
version: true,
166+
query: {
167+
language: 'kuery',
168+
query: '',
169+
},
170+
filter: [
171+
{
172+
meta: {
173+
alias: null,
174+
negate: false,
175+
disabled: false,
176+
type: 'phrase',
177+
key: 'airline',
178+
params: {
179+
query: 'AAL',
180+
},
181+
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index',
182+
},
183+
query: {
184+
match_phrase: {
185+
airline: 'AAL',
186+
},
187+
},
188+
$state: {
189+
store: 'appState',
190+
},
191+
},
192+
],
193+
indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index',
194+
};
195+
savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify(searchSource);
196+
197+
const resp = createSearchItems(kibanaConfig, indexPattern, savedSearch);
198+
expect(resp).toStrictEqual({
199+
combinedQuery: {
200+
bool: {
201+
must: [{ match_all: {} }],
202+
filter: [{ match_phrase: { airline: 'AAL' } }],
203+
must_not: [],
204+
},
205+
},
206+
query: { language: 'kuery', query: '' },
207+
});
208+
});
209+
});

x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,16 @@ export function createSearchItems(
5252
}
5353
const filterQuery = esQuery.buildQueryFromFilters(filters, indexPattern);
5454

55-
if (combinedQuery.bool.filter === undefined) {
56-
combinedQuery.bool.filter = [];
55+
if (Array.isArray(combinedQuery.bool.filter) === false) {
56+
combinedQuery.bool.filter =
57+
combinedQuery.bool.filter === undefined ? [] : [combinedQuery.bool.filter];
5758
}
58-
if (combinedQuery.bool.must_not === undefined) {
59-
combinedQuery.bool.must_not = [];
59+
60+
if (Array.isArray(combinedQuery.bool.must_not) === false) {
61+
combinedQuery.bool.must_not =
62+
combinedQuery.bool.must_not === undefined ? [] : [combinedQuery.bool.must_not];
6063
}
64+
6165
combinedQuery.bool.filter = [...combinedQuery.bool.filter, ...filterQuery.filter];
6266
combinedQuery.bool.must_not = [...combinedQuery.bool.must_not, ...filterQuery.must_not];
6367
} else {

0 commit comments

Comments
 (0)