如何扩展GraphQL过滤器实现多关键词搜索?
实现HotChocolate GraphQL多关键词OR逻辑的Contains过滤扩展
你需要修改MyStringContainsHandler的HandleOperation方法,将输入字符串拆分为独立关键词,为每个关键词生成Contains表达式,再通过OR逻辑组合这些表达式,即可匹配包含任意一个关键词的条目。
修改后的完整代码
public class MyGqlFilterConvention : FilterConvention { protected override void Configure(IFilterConventionDescriptor descriptor) { descriptor.AddDefaultOperations(); descriptor.AddDefaults(); descriptor.AddProviderExtension( new QueryableFilterProviderExtension(y => y.AddFieldHandler<MyStringContainsHandler>())); } } public class MyStringContainsHandler : QueryableStringOperationHandler { protected override int Operation => DefaultFilterOperations.Contains; public override Expression HandleOperation(QueryableFilterContext context, IFilterOperationField field, IValueNode value, object parsedValue) { var property = context.GetInstance(); var inputString = parsedValue as string; // 非字符串输入按原逻辑处理 if (string.IsNullOrWhiteSpace(inputString)) { return FilterExpressionBuilder.Contains(Expression.Call(property), parsedValue); } // 拆分关键词:按空格分割,过滤空值并去重 var keywords = inputString.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) .Distinct(StringComparer.OrdinalIgnoreCase); // 无有效关键词时返回永远不匹配的表达式 if (!keywords.Any()) { return Expression.Constant(false); } // 为第一个关键词生成初始表达式 Expression combinedExpression = FilterExpressionBuilder.Contains( Expression.Call(property), keywords.First(), StringComparison.OrdinalIgnoreCase); // 可选:忽略大小写匹配 // 用OR逻辑组合剩余关键词的表达式 foreach (var keyword in keywords.Skip(1)) { var containsExpr = FilterExpressionBuilder.Contains( Expression.Call(property), keyword, StringComparison.OrdinalIgnoreCase); combinedExpression = Expression.OrElse(combinedExpression, containsExpr); } return combinedExpression; } }
关键修改说明
- 关键词拆分与清洗:用
Split按空格分割输入字符串,通过RemoveEmptyEntries过滤空关键词,Distinct避免重复匹配相同关键词。 - 表达式组合:
- 先为第一个关键词生成基础的
Contains表达式 - 遍历剩余关键词,用
Expression.OrElse将每个关键词的Contains表达式以OR逻辑组合
- 先为第一个关键词生成基础的
- 可选优化:添加
StringComparison.OrdinalIgnoreCase实现大小写不敏感匹配,可根据业务需求移除。 - 边界处理:对空输入、无有效关键词的场景做兜底处理,避免运行时异常。
内容的提问来源于stack exchange,提问作者Vondool
相关产品推荐
相关产品推荐

