From a1987445534be700e575e0b1831e47b63c71a9f4 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Wed, 10 Mar 2021 14:36:23 -0500 Subject: [PATCH] [App Search] Fixed 2 relevance tuning bugs (#94312) --- .../boost_item_content/boost_item_content.tsx | 8 ++--- .../functional_boost_form.test.tsx | 5 +-- .../functional_boost_form.tsx | 6 ++-- .../proximity_boost_form.test.tsx | 10 +++--- .../proximity_boost_form.tsx | 4 +-- .../value_boost_form.test.tsx | 6 ++-- .../boost_item_content/value_boost_form.tsx | 4 +-- .../relevance_tuning/boosts/boosts.test.tsx | 18 ++++++++++ .../relevance_tuning/boosts/boosts.tsx | 4 ++- .../components/relevance_tuning/constants.ts | 35 +++++++++++++++++++ .../relevance_tuning_logic.test.ts | 6 ++++ .../relevance_tuning_logic.ts | 16 +++------ .../components/relevance_tuning/types.ts | 30 +++++++++++----- 13 files changed, 112 insertions(+), 40 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/boost_item_content.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/boost_item_content.tsx index f83ec99acb1acb..7b9dd6b26cbb2b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/boost_item_content.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/boost_item_content.tsx @@ -13,7 +13,7 @@ import { EuiButton, EuiFormRow, EuiPanel, EuiRange, EuiSpacer } from '@elastic/e import { i18n } from '@kbn/i18n'; import { RelevanceTuningLogic } from '../..'; -import { Boost, BoostType } from '../../types'; +import { Boost, BoostType, FunctionalBoost, ProximityBoost, ValueBoost } from '../../types'; import { FunctionalBoostForm } from './functional_boost_form'; import { ProximityBoostForm } from './proximity_boost_form'; @@ -32,11 +32,11 @@ export const BoostItemContent: React.FC = ({ boost, index, name }) => { const getBoostForm = () => { switch (type) { case BoostType.Value: - return ; + return ; case BoostType.Functional: - return ; + return ; case BoostType.Proximity: - return ; + return ; } }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/functional_boost_form.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/functional_boost_form.test.tsx index 11a224a71d7f82..feb4328e5adea1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/functional_boost_form.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/functional_boost_form.test.tsx @@ -13,12 +13,13 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { EuiSelect } from '@elastic/eui'; -import { Boost, BoostOperation, BoostType, FunctionalBoostFunction } from '../../types'; +import { FunctionalBoost, BoostOperation, BoostType, FunctionalBoostFunction } from '../../types'; import { FunctionalBoostForm } from './functional_boost_form'; describe('FunctionalBoostForm', () => { - const boost: Boost = { + const boost: FunctionalBoost = { + value: undefined, factor: 2, type: 'functional' as BoostType, function: 'logarithmic' as FunctionalBoostFunction, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/functional_boost_form.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/functional_boost_form.tsx index d677fe5cbc069a..ebd826dcd27efa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/functional_boost_form.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/functional_boost_form.tsx @@ -19,7 +19,7 @@ import { FUNCTIONAL_BOOST_FUNCTION_DISPLAY_MAP, } from '../../constants'; import { - Boost, + FunctionalBoost, BoostFunction, BoostOperation, BoostType, @@ -27,7 +27,7 @@ import { } from '../../types'; interface Props { - boost: Boost; + boost: FunctionalBoost; index: number; name: string; } @@ -39,7 +39,7 @@ const functionOptions = Object.values(FunctionalBoostFunction).map((boostFunctio const operationOptions = Object.values(BoostOperation).map((boostOperation) => ({ value: boostOperation, - text: BOOST_OPERATION_DISPLAY_MAP[boostOperation as BoostOperation], + text: BOOST_OPERATION_DISPLAY_MAP[boostOperation], })); export const FunctionalBoostForm: React.FC = ({ boost, index, name }) => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/proximity_boost_form.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/proximity_boost_form.test.tsx index 6abbcc3d988625..0ed914abb3ab5e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/proximity_boost_form.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/proximity_boost_form.test.tsx @@ -13,12 +13,14 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { EuiFieldText, EuiSelect } from '@elastic/eui'; -import { Boost, BoostType, ProximityBoostFunction } from '../../types'; +import { ProximityBoost, BoostType, ProximityBoostFunction } from '../../types'; import { ProximityBoostForm } from './proximity_boost_form'; describe('ProximityBoostForm', () => { - const boost: Boost = { + const boost: ProximityBoost = { + value: undefined, + operation: undefined, factor: 2, type: 'proximity' as BoostType, function: 'linear' as ProximityBoostFunction, @@ -46,8 +48,8 @@ describe('ProximityBoostForm', () => { describe('various boost values', () => { const renderWithBoostValues = (boostValues: { - center?: Boost['center']; - function?: Boost['function']; + center?: ProximityBoost['center']; + function?: ProximityBoost['function']; }) => { return shallow( { - const boost: Boost = { + const boost: ValueBoost = { + operation: undefined, + function: undefined, factor: 2, type: 'value' as BoostType, value: ['bar', '', 'baz'], diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/value_boost_form.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/value_boost_form.tsx index 7fcd07d9a07aad..cd65f2842a5f7f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/value_boost_form.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item_content/value_boost_form.tsx @@ -20,10 +20,10 @@ import { import { i18n } from '@kbn/i18n'; import { RelevanceTuningLogic } from '../..'; -import { Boost } from '../../types'; +import { ValueBoost } from '../../types'; interface Props { - boost: Boost; + boost: ValueBoost; index: number; name: string; } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.test.tsx index 8a355b97e7b9ff..9f6e194f927356 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.test.tsx @@ -78,6 +78,24 @@ describe('Boosts', () => { expect(select.prop('options').map((o: any) => o.value)).toEqual(['add-boost', 'proximity']); }); + it('will not render functional option if "type" prop is "date"', () => { + const wrapper = shallow( + + ); + + const select = wrapper.find(EuiSuperSelect); + expect(select.prop('options').map((o: any) => o.value)).toEqual([ + 'add-boost', + 'proximity', + 'value', + ]); + }); + it('will add a boost of the selected type when a selection is made', () => { const wrapper = shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.tsx index 4268e211102770..0aa1753938f46f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.tsx @@ -13,7 +13,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle, EuiSuperSelect } from '@ import { i18n } from '@kbn/i18n'; -import { GEOLOCATION, TEXT } from '../../../../shared/constants/field_types'; +import { GEOLOCATION, TEXT, DATE } from '../../../../shared/constants/field_types'; import { SchemaTypes } from '../../../../shared/types'; import { BoostIcon } from '../boost_icon'; @@ -70,6 +70,8 @@ const filterInvalidOptions = (value: BoostType, type: SchemaTypes) => { if (type === TEXT && [BoostType.Proximity, BoostType.Functional].includes(value)) return false; // Value and Functional boost types are not valid for geolocation fields if (type === GEOLOCATION && [BoostType.Functional, BoostType.Value].includes(value)) return false; + // Functional boosts are not valid for date fields + if (type === DATE && value === BoostType.Functional) return false; return true; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/constants.ts index 8131a6a3a57c64..181ecad9e99903 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/constants.ts @@ -10,8 +10,11 @@ import { i18n } from '@kbn/i18n'; import { BoostOperation, BoostType, + FunctionalBoost, FunctionalBoostFunction, + ProximityBoost, ProximityBoostFunction, + ValueBoost, } from './types'; export const FIELD_FILTER_CUTOFF = 10; @@ -77,6 +80,38 @@ export const BOOST_TYPE_TO_ICON_MAP = { [BoostType.Proximity]: 'tokenGeo', }; +const EMPTY_VALUE_BOOST: ValueBoost = { + type: BoostType.Value, + factor: 1, + newBoost: true, + function: undefined, + operation: undefined, +}; + +const EMPTY_FUNCTIONAL_BOOST: FunctionalBoost = { + value: undefined, + type: BoostType.Functional, + factor: 1, + newBoost: true, + function: FunctionalBoostFunction.Logarithmic, + operation: BoostOperation.Multiply, +}; + +const EMPTY_PROXIMITY_BOOST: ProximityBoost = { + value: undefined, + type: BoostType.Proximity, + factor: 1, + newBoost: true, + operation: undefined, + function: ProximityBoostFunction.Gaussian, +}; + +export const BOOST_TYPE_TO_EMPTY_BOOST = { + [BoostType.Value]: EMPTY_VALUE_BOOST, + [BoostType.Functional]: EMPTY_FUNCTIONAL_BOOST, + [BoostType.Proximity]: EMPTY_PROXIMITY_BOOST, +}; + export const ADD_DISPLAY = i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.boosts.addOperationDropDownOptionLabel', { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts index bcb8ad8a584a56..f0fe98f3f0a878 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts @@ -719,6 +719,9 @@ describe('RelevanceTuningLogic', () => { factor: 1, newBoost: true, type: BoostType.Functional, + function: 'logarithmic', + operation: 'multiply', + value: undefined, }, ], }, @@ -744,6 +747,9 @@ describe('RelevanceTuningLogic', () => { factor: 1, newBoost: true, type: BoostType.Functional, + function: 'logarithmic', + operation: 'multiply', + value: undefined, }, ], }, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts index 0d30296de285ff..588b100416d10c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts @@ -20,15 +20,9 @@ import { RESET_CONFIRMATION_MESSAGE, DELETE_SUCCESS_MESSAGE, DELETE_CONFIRMATION_MESSAGE, + BOOST_TYPE_TO_EMPTY_BOOST, } from './constants'; -import { - BaseBoost, - Boost, - BoostFunction, - BoostOperation, - BoostType, - SearchSettings, -} from './types'; +import { Boost, BoostFunction, BoostOperation, BoostType, SearchSettings } from './types'; import { filterIfTerm, parseBoostCenter, @@ -87,12 +81,12 @@ interface RelevanceTuningActions { updateBoostSelectOption( name: string, boostIndex: number, - optionType: keyof BaseBoost, + optionType: keyof Pick, value: BoostOperation | BoostFunction ): { name: string; boostIndex: number; - optionType: keyof BaseBoost; + optionType: keyof Pick; value: string; }; updateSearchValue(query: string): string; @@ -376,7 +370,7 @@ export const RelevanceTuningLogic = kea< addBoost: ({ name, type }) => { const { searchSettings } = values; const { boosts } = searchSettings; - const emptyBoost = { type, factor: 1, newBoost: true }; + const emptyBoost = BOOST_TYPE_TO_EMPTY_BOOST[type]; let boostArray; if (Array.isArray(boosts[name])) { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/types.ts index 16da5868da6819..ec42df218878f9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/types.ts @@ -29,26 +29,38 @@ export enum BoostOperation { Add = 'add', Multiply = 'multiply', } - -export interface BaseBoost { +export interface Boost { + type: BoostType; operation?: BoostOperation; function?: BoostFunction; + newBoost?: boolean; + center?: string | number; + factor: number; + value?: string[]; } // A boost that comes from the server, before we normalize it has a much looser schema -export interface RawBoost extends BaseBoost { - type: BoostType; - newBoost?: boolean; - center?: string | number; +export interface RawBoost extends Omit { value?: string | number | boolean | object | Array; - factor: number; } -// We normalize raw boosts to make them safer and easier to work with -export interface Boost extends RawBoost { +export interface ValueBoost extends Boost { value?: string[]; + operation: undefined; + function: undefined; } +export interface FunctionalBoost extends Boost { + value: undefined; + operation: BoostOperation; + function: FunctionalBoostFunction; +} + +export interface ProximityBoost extends Boost { + value: undefined; + operation: undefined; + function: ProximityBoostFunction; +} export interface SearchField { weight: number; }