目前在搜索组件中使用的下拉列表是由ES使用术语聚合驱动的。下拉列表在选中时应该过滤其他下拉列表,但不会进一步过滤自身。我目前基本上正在进行两次搜索来完成这一点,并从两次搜索中收集聚合。第一次是大小为0,给定的查询不包括最近应用的过滤器:
(为岗位简化)
// for aggregation on last filter selected
var newestFilterResponse = await _client.SearchAsync<Index>(s => s
.Index(_index)
.From(0)
.Size(0)
.Query(QueryClosure(phrase, fields, filtersMinusLast))
.Aggregations(FilterOptionsAggregationClosure(lastFilter)));
// actual query for results and aggregation on other filters
var response = await _client.SearchAsync<Index>(s => s
.Index(_index)
.From(0)
.Size(500)
.Query(QueryClosure(phrase, fields, allFilters))
.Aggregations(FilterOptionsAggregationClosure(allFiltersExceptLast)));
使用下面为每个下拉列表构建术语聚合
Func<AggregationContainerDescriptor<Index>, IAggregationContainer> FilterOptionsAggregationClosure(List<FilterButton> filterButtons)
{
return delegate (AggregationContainerDescriptor<Index> aggregationContainerDescriptor)
{
foreach (var filterButton in filterButtons)
{
aggregationContainerDescriptor = aggregationContainerDescriptor
.Terms(filterButton.AggregationName, t => t
.Field(filterButton.FieldToSearch)
.Size(10000)
);
}
return aggregationContainerDescriptor;
};
}
使用下面的代码来构建查询(例如,简化为仅筛选,但在我的实际用例中有多匹配、前缀等)
Func<QueryContainerDescriptor<Index>, QueryContainer> QueryClosure(string phrase, Fields fields, List<FilterApplied> filtersApplied)
{
return delegate (QueryContainerDescriptor<Index> queryContainerDescriptor)
{
// multimatch, prefix, etc. on phrase for fields supplied
QueryContainer queryContainer = GetKeywordQuery(phrase, fields);
QueryContainer filterQuery = new();
foreach (var filter in filtersApplied)
{
QueryContainer sameFilterQuery = new QueryContainerDescriptor<Index>()
.Bool(boolQuery => boolQuery
.Filter(f => f
.Terms(terms => terms
.Field(filter.FieldToSearch)
.Terms(filter.Values))));
filterQuery = filterQuery && sameFilterQuery;
}
return queryContainer && filterQuery;
};
}
我觉得这不是办法。任何改进的建议都将不胜感激。谢谢!
1条答案
按热度按时间dnph8jn41#
最终在会话存储中缓存下拉选项,我们希望url参数能够在共享链接时生成准确的页面状态,但最终放弃了过滤器下拉状态,这样我们就可以消除对最后应用的过滤器类型进行隔离聚合的需要