Skip to content

Commit

Permalink
Merge pull request #4090 from microsoft-search/fix/3934
Browse files Browse the repository at this point in the history
Fix/3934
  • Loading branch information
wobba authored Nov 12, 2024
2 parents e1ba830 + 7dfd618 commit 60ee464
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 14 deletions.
17 changes: 9 additions & 8 deletions search-parts/src/dataSources/MicrosoftSearchDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -755,16 +755,17 @@ export class MicrosoftSearchDataSource extends BaseDataSource<IMicrosoftSearchDa

// Build aggregation filters
if (dataContext.filters.selectedFilters.length > 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;
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions search-parts/src/dataSources/SharePointSearchDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -896,13 +896,13 @@ export class SharePointSearchDataSource extends BaseDataSource<ISharePointSearch

// 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(',');
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));
}
}

Expand Down
60 changes: 56 additions & 4 deletions search-parts/src/helpers/DataFilterHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,72 @@ 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): string {
let refinementQueryConditions: string[] = [];
selectedFilters.forEach(filter => {

const { filterName, values } = filter;

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;
}
}
else {
return `${filterName}:"${refinement.name}"`;
}
}).filter(c => c);

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
? 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[] = [];

selectedFilters.forEach(filter => {

let operator: any = filter.operator;

// Mutli values
// Multi values
if (filter.values.length > 1) {

let startDate = null;
Expand All @@ -108,7 +161,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";
Expand Down

0 comments on commit 60ee464

Please sign in to comment.