From 0cc4577742608ce5e99b1d68ae94499aff3117fe Mon Sep 17 00:00:00 2001 From: Mikael Svenson Date: Sat, 9 Nov 2024 17:55:48 +0100 Subject: [PATCH 1/4] Remove unused parameter --- search-parts/src/dataSources/SharePointSearchDataSource.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/search-parts/src/dataSources/SharePointSearchDataSource.ts b/search-parts/src/dataSources/SharePointSearchDataSource.ts index 10cc360a..56880285 100644 --- a/search-parts/src/dataSources/SharePointSearchDataSource.ts +++ b/search-parts/src/dataSources/SharePointSearchDataSource.ts @@ -896,13 +896,13 @@ export class SharePointSearchDataSource extends BaseDataSource 1 && dataContext.filters.selectedFilters.filter(selectedFilter => selectedFilter.values.length > 0).length > 1) { - const refinementString = DataFilterHelper.buildFqlRefinementString(dataContext.filters.selectedFilters, dataContext.filters.filtersConfiguration, this.moment).join(','); + const refinementString = DataFilterHelper.buildFqlRefinementString(dataContext.filters.selectedFilters, this.moment).join(','); if (!isEmpty(refinementString)) { refinementFilters = refinementFilters.concat([`${dataContext.filters.filterOperator}(${refinementString})`]); } } else { - refinementFilters = refinementFilters.concat(DataFilterHelper.buildFqlRefinementString(dataContext.filters.selectedFilters, dataContext.filters.filtersConfiguration, this.moment)); + refinementFilters = refinementFilters.concat(DataFilterHelper.buildFqlRefinementString(dataContext.filters.selectedFilters, this.moment)); } } From a2b69735f1420b1ebc0da31addcf8e91096a3227 Mon Sep 17 00:00:00 2001 From: Mikael Svenson Date: Sat, 9 Nov 2024 17:56:12 +0100 Subject: [PATCH 2/4] Support OR for filters using KQL and query template --- .../dataSources/MicrosoftSearchDataSource.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/search-parts/src/dataSources/MicrosoftSearchDataSource.ts b/search-parts/src/dataSources/MicrosoftSearchDataSource.ts index af653cb5..1301f514 100644 --- a/search-parts/src/dataSources/MicrosoftSearchDataSource.ts +++ b/search-parts/src/dataSources/MicrosoftSearchDataSource.ts @@ -755,16 +755,17 @@ export class MicrosoftSearchDataSource extends BaseDataSource 0) { - - // Make sure, if we have multiple filters, at least two filters have values to avoid apply an operator ('or','and') on only one condition failing the query. - if (dataContext.filters.selectedFilters.length > 1 && dataContext.filters.selectedFilters.filter(selectedFilter => selectedFilter.values.length > 0).length > 1) { - const refinementString = DataFilterHelper.buildFqlRefinementString(dataContext.filters.selectedFilters, dataContext.filters.filtersConfiguration, this.moment).join(','); - if (!isEmpty(refinementString)) { - aggregationFilters = aggregationFilters.concat([`${dataContext.filters.filterOperator}(${refinementString})`]); + if (dataContext.filters.filterOperator === 'and') { + // Make sure, if we have multiple filters, at least two filters have values to avoid apply an operator ('or','and') on only one condition failing the query. + const refinementStrings = DataFilterHelper.buildFqlRefinementString(dataContext.filters.selectedFilters, this.moment); + if (!isEmpty(refinementStrings)) { + aggregationFilters = aggregationFilters.concat(refinementStrings); } - } else { - aggregationFilters = aggregationFilters.concat(DataFilterHelper.buildFqlRefinementString(dataContext.filters.selectedFilters, dataContext.filters.filtersConfiguration, this.moment)); + const refinementStrings = DataFilterHelper.buildKqlRefinementString(dataContext.filters.selectedFilters, this.moment); + if (!isEmpty(refinementStrings)) { + queryTemplate = refinementStrings ? `${queryTemplate} AND ${refinementStrings}` : queryTemplate; + } } } From a502461c760edf0c00324d399da4e0a1e27c4ba1 Mon Sep 17 00:00:00 2001 From: Mikael Svenson Date: Sat, 9 Nov 2024 17:56:35 +0100 Subject: [PATCH 3/4] Add support for KQL filter building Removed unused parameter --- search-parts/src/helpers/DataFilterHelper.ts | 52 ++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/search-parts/src/helpers/DataFilterHelper.ts b/search-parts/src/helpers/DataFilterHelper.ts index 297e5283..eab23198 100644 --- a/search-parts/src/helpers/DataFilterHelper.ts +++ b/search-parts/src/helpers/DataFilterHelper.ts @@ -81,11 +81,56 @@ export class DataFilterHelper { /** * Build the refinement condition in FQL format * @param selectedFilters The selected filter array - * @param filtersConfiguration The current filters configuration * @param moment The moment.js instance to resolve dates * @param encodeTokens If true, encodes the taxonomy refinement tokens in UTF-8 to work with GET requests. Javascript encodes natively in UTF-16 by default. */ - public static buildFqlRefinementString(selectedFilters: IDataFilter[], filtersConfiguration: IDataFilterConfiguration[], moment: any, encodeTokens?: boolean): string[] { + public static buildKqlRefinementString(selectedFilters: IDataFilter[], moment: any, encodeTokens?: boolean): string { + let refinementQueryConditions: string[] = []; + selectedFilters.forEach(filter => { + + const { filterName, values } = filter; + + if (values && values.length > 0) { + let startDate = null; + let endDate = null; + const fieldValues = values + .map(refinement => { + if (moment(refinement.value, moment.ISO_8601, true).isValid()) { + if (!startDate && (refinement.operator === FilterComparisonOperator.Geq || refinement.operator === FilterComparisonOperator.Gt)) { + startDate = refinement.value; + } + + if (!endDate && (refinement.operator === FilterComparisonOperator.Lt || refinement.operator === FilterComparisonOperator.Leq)) { + endDate = refinement.value; + } + } + else { + return `${filterName}:"${refinement.name}"`; + } + }).filter(c => c); + + if (startDate && endDate) { + refinementQueryConditions.push(`${filter.filterName}:${startDate}..${endDate}`); + } + else { + const joinedFieldValues = fieldValues.length > 1 + ? fieldValues.join(` ${filter.operator === 'or' ? "OR" : "AND"} `) + : fieldValues[0]; + refinementQueryConditions.push(`(${joinedFieldValues})`); + } + } + }); + + return refinementQueryConditions.join(" OR "); // only used when building aggregation with OR between filters + } + + /** + * Build the refinement condition in FQL format + * @param selectedFilters The selected filter array + * @param moment The moment.js instance to resolve dates + * @param encodeTokens If true, encodes the taxonomy refinement tokens in UTF-8 to work with GET requests. Javascript encodes natively in UTF-16 by default. + */ + public static buildFqlRefinementString(selectedFilters: IDataFilter[], moment: any, encodeTokens?: boolean): string[] { let refinementQueryConditions: string[] = []; @@ -93,7 +138,7 @@ export class DataFilterHelper { let operator: any = filter.operator; - // Mutli values + // Multi values if (filter.values.length > 1) { let startDate = null; @@ -108,7 +153,6 @@ export class DataFilterHelper { let value = filterValue.value; if (moment(value, moment.ISO_8601, true).isValid()) { - if (!startDate && (filterValue.operator === FilterComparisonOperator.Geq || filterValue.operator === FilterComparisonOperator.Gt)) { startDate = value; startBehaviour = filterValue.operator === FilterComparisonOperator.Gt ? "GT" : "GE"; From 7dfd618ab1f0aec947d60cd9f43f28690c97a75f Mon Sep 17 00:00:00 2001 From: Mikael Svenson Date: Sat, 9 Nov 2024 18:11:44 +0100 Subject: [PATCH 4/4] Fix logic --- search-parts/src/helpers/DataFilterHelper.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/search-parts/src/helpers/DataFilterHelper.ts b/search-parts/src/helpers/DataFilterHelper.ts index eab23198..192a95f1 100644 --- a/search-parts/src/helpers/DataFilterHelper.ts +++ b/search-parts/src/helpers/DataFilterHelper.ts @@ -84,7 +84,7 @@ export class DataFilterHelper { * @param moment The moment.js instance to resolve dates * @param encodeTokens If true, encodes the taxonomy refinement tokens in UTF-8 to work with GET requests. Javascript encodes natively in UTF-16 by default. */ - public static buildKqlRefinementString(selectedFilters: IDataFilter[], moment: any, encodeTokens?: boolean): string { + public static buildKqlRefinementString(selectedFilters: IDataFilter[], moment: any): string { let refinementQueryConditions: string[] = []; selectedFilters.forEach(filter => { @@ -93,14 +93,17 @@ export class DataFilterHelper { if (values && values.length > 0) { let startDate = null; let endDate = null; + let dateOperator = null; const fieldValues = values .map(refinement => { if (moment(refinement.value, moment.ISO_8601, true).isValid()) { if (!startDate && (refinement.operator === FilterComparisonOperator.Geq || refinement.operator === FilterComparisonOperator.Gt)) { + dateOperator = ">="; startDate = refinement.value; } if (!endDate && (refinement.operator === FilterComparisonOperator.Lt || refinement.operator === FilterComparisonOperator.Leq)) { + dateOperator = "<"; endDate = refinement.value; } } @@ -111,6 +114,11 @@ export class DataFilterHelper { if (startDate && endDate) { refinementQueryConditions.push(`${filter.filterName}:${startDate}..${endDate}`); + } else if (startDate){ + refinementQueryConditions.push(`${filter.filterName}${dateOperator}${startDate}`); + } + else if (endDate){ + refinementQueryConditions.push(`${filter.filterName}${dateOperator}${endDate}`); } else { const joinedFieldValues = fieldValues.length > 1