From 4490a4b4072ecd911bbdd4f079d78973a62e11b4 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Wed, 15 Jul 2020 22:15:39 +0100 Subject: [PATCH] [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 --- .../jobs/new_job/utils/new_job_utils.test.ts | 209 ++++++++++++++++++ .../jobs/new_job/utils/new_job_utils.ts | 12 +- 2 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.test.ts diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.test.ts b/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.test.ts new file mode 100644 index 0000000000000..b7c29abc96fb8 --- /dev/null +++ b/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.test.ts @@ -0,0 +1,209 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IUiSettingsClient } from 'kibana/public'; +import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns'; +import { SavedSearchSavedObject } from '../../../../../common/types/kibana'; +import { createSearchItems } from './new_job_utils'; + +describe('createSearchItems', () => { + const kibanaConfig = {} as IUiSettingsClient; + const indexPattern = ({ + fields: [], + } as unknown) as IIndexPattern; + + let savedSearch = ({} as unknown) as SavedSearchSavedObject; + beforeEach(() => { + savedSearch = ({ + client: { + http: { + basePath: { + basePath: '/abc', + serverBasePath: '/abc', + }, + anonymousPaths: {}, + }, + batchQueue: [], + }, + attributes: { + title: 'not test', + description: '', + hits: 0, + columns: ['_source'], + sort: [], + version: 1, + kibanaSavedObjectMeta: { + searchSourceJSON: '', + }, + }, + _version: 'WzI0OSw0XQ==', + id: '4b9b1010-c678-11ea-b6e6-e942978da29c', + type: 'search', + migrationVersion: { + search: '7.4.0', + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: '7e252840-bd27-11ea-8a6c-75d1a0bd08ab', + }, + ], + } as unknown) as SavedSearchSavedObject; + }); + + test('should match index pattern', () => { + const resp = createSearchItems(kibanaConfig, indexPattern, null); + expect(resp).toStrictEqual({ + combinedQuery: { bool: { must: [{ match_all: {} }] } }, + query: { query: '', language: 'lucene' }, + }); + }); + + test('should match saved search with kuery and condition', () => { + const searchSource = { + highlightAll: true, + version: true, + query: { query: 'airline : "AAL" ', language: 'kuery' }, + filter: [], + indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index', + }; + savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify(searchSource); + + const resp = createSearchItems(kibanaConfig, indexPattern, savedSearch); + expect(resp).toStrictEqual({ + combinedQuery: { + bool: { + should: [{ match_phrase: { airline: 'AAL' } }], + minimum_should_match: 1, + filter: [], + must_not: [], + }, + }, + query: { + language: 'kuery', + query: 'airline : "AAL" ', + }, + }); + }); + + test('should match saved search with kuery and not condition', () => { + const searchSource = { + highlightAll: true, + version: true, + query: { query: 'NOT airline : "AAL" ', language: 'kuery' }, + filter: [], + indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index', + }; + savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify(searchSource); + + const resp = createSearchItems(kibanaConfig, indexPattern, savedSearch); + expect(resp).toStrictEqual({ + combinedQuery: { + bool: { + filter: [], + must_not: [ + { + bool: { + minimum_should_match: 1, + should: [ + { + match_phrase: { + airline: 'AAL', + }, + }, + ], + }, + }, + ], + }, + }, + query: { + language: 'kuery', + query: 'NOT airline : "AAL" ', + }, + }); + }); + + test('should match saved search with kuery and condition and not condition', () => { + const searchSource = { + highlightAll: true, + version: true, + query: { query: 'airline : "AAL" and NOT airline : "AWE" ', language: 'kuery' }, + filter: [], + indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index', + }; + savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify(searchSource); + + const resp = createSearchItems(kibanaConfig, indexPattern, savedSearch); + expect(resp).toStrictEqual({ + combinedQuery: { + bool: { + filter: [ + { bool: { should: [{ match_phrase: { airline: 'AAL' } }], minimum_should_match: 1 } }, + { + bool: { + must_not: { + bool: { should: [{ match_phrase: { airline: 'AWE' } }], minimum_should_match: 1 }, + }, + }, + }, + ], + must_not: [], + }, + }, + query: { query: 'airline : "AAL" and NOT airline : "AWE" ', language: 'kuery' }, + }); + }); + + test('should match saved search with kuery and filter', () => { + const searchSource = { + highlightAll: true, + version: true, + query: { + language: 'kuery', + query: '', + }, + filter: [ + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'airline', + params: { + query: 'AAL', + }, + indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index', + }, + query: { + match_phrase: { + airline: 'AAL', + }, + }, + $state: { + store: 'appState', + }, + }, + ], + indexRefName: 'kibanaSavedObjectMeta.searchSourceJSON.index', + }; + savedSearch.attributes.kibanaSavedObjectMeta.searchSourceJSON = JSON.stringify(searchSource); + + const resp = createSearchItems(kibanaConfig, indexPattern, savedSearch); + expect(resp).toStrictEqual({ + combinedQuery: { + bool: { + must: [{ match_all: {} }], + filter: [{ match_phrase: { airline: 'AAL' } }], + must_not: [], + }, + }, + query: { language: 'kuery', query: '' }, + }); + }); +}); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts b/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts index 9ba10dc21000e..5fa6c817ec4c1 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/utils/new_job_utils.ts @@ -52,12 +52,16 @@ export function createSearchItems( } const filterQuery = esQuery.buildQueryFromFilters(filters, indexPattern); - if (combinedQuery.bool.filter === undefined) { - combinedQuery.bool.filter = []; + if (Array.isArray(combinedQuery.bool.filter) === false) { + combinedQuery.bool.filter = + combinedQuery.bool.filter === undefined ? [] : [combinedQuery.bool.filter]; } - if (combinedQuery.bool.must_not === undefined) { - combinedQuery.bool.must_not = []; + + if (Array.isArray(combinedQuery.bool.must_not) === false) { + combinedQuery.bool.must_not = + combinedQuery.bool.must_not === undefined ? [] : [combinedQuery.bool.must_not]; } + combinedQuery.bool.filter = [...combinedQuery.bool.filter, ...filterQuery.filter]; combinedQuery.bool.must_not = [...combinedQuery.bool.must_not, ...filterQuery.must_not]; } else {