Ok, I think I got it, but need to do some thorough tests
Here is what I came up with:
/**
* Filter list of ABLIS services with a given list of filters.
*
* Notes:
* - A serviceSearcher is the "category" to filter by (ie) Topic, Level, Type, Agency
* - When selecting multiple filters across "cateogies", the filter uses an AND condition.
* - When selecting multiple filters inside a serviceSearcher, the filter uses an OR condition.
*
* @param services List of ABLIS Service records
* @param filters List of Filter definition
*/
export function filterServices(services: Service[], filters: ServiceFilterItem[]): Service[] {
// 1. Strict filter match across multiple cateogory selections
const strictMatch = services.filter((service: Service) => {
const flattenedFilters = new Set(filters.map((filter) => filter.searchTerm));
// loop through category items to create an AND condition (intersection using the searchPath)
const match = filters.every((path) => {
// for every search path check all services from lazy filter search
const values: string[] = JSONPath({
path: path.serviceSearcher,
json: service,
});
// check if any of the checked filter values for each category are shared
return flattenedFilters.has(values[0]);
});
return match;
});
return strictMatch;
}