.NET环境下HotChocolate动态Schema与自定义过滤实现咨询
1、硬编码场景添加自定义过滤字段
继承FilterInputType<T>,在配置方法中显式声明自定义过滤字段并绑定对应属性访问逻辑即可,示例代码如下:
// 自定义Product的过滤输入类型 public class ProductFilterInputType : FilterInputType<Product> { protected override void Configure(IFilterInputTypeDescriptor<Product> descriptor) { // 可选:显式绑定字段,避免自动挂载所有原生字段 descriptor.BindFieldsExplicitly(); // 挂载原有原生字段 descriptor.Field(p => p.Id); descriptor.Field(p => p.ProductType); // 挂载自定义过滤字段 descriptor.Field("lengthInMeter") // 指定该字段支持的操作符类型,int类型对应IntOperationFilterInputType .Type<IntOperationFilterInputType>() // 绑定字段对应的属性访问表达式,供过滤生成IQueryable使用 .Filter(p => p.Specific.ContainsKey("shoeSize") ? (int)p.Specific["shoeSize"] : 0); } }
配置完成后,需要将该过滤类型和对应的查询字段绑定,有两种方式:
- 全局注册:在AddGraphQL配置链中添加
AddFiltering().AddFilterType<ProductFilterInputType>(),作为Product类型的默认过滤器 - 单独绑定:在查询字段的 descriptor 上添加
UseFiltering(typeof(ProductFilterInputType))
配置完成后就可以正常使用where: { lengthInMeter: { gt: 4 } }的过滤语法。
2、动态生成FilterInputType
按照官方TypeModules动态构造Schema的方案,你需要额外完成以下几步:
- 构造动态ObjectType的同时,同步构造对应的
FilterInputTypeDefinition实例 - 遍历CMS配置中新增的动态字段,为每个字段生成对应的
InputFieldDefinition,字段类型匹配对应的操作输入类型(比如字符串对应StringOperationFilterInputType,布尔值对应BooleanOperationFilterInputType) - 为每个动态过滤字段添加元数据:以
FilterMetadataKeys.Expression为Key,Value为该字段对应的属性访问Lambda表达式,和硬编码场景的Filter方法传入的表达式逻辑一致 - 将构造完成的
FilterInputTypeDefinition注册到类型系统中,同时将该过滤器和你对应的产品查询字段绑定
之前仅创建Definition不生效的核心原因是没有将动态生成的过滤器类型和查询字段的过滤中间件完成绑定。
3、IQueryable转译与拦截逻辑
只要你绑定的属性访问表达式符合CosmosDB LINQ Provider的语法规则,HotChocolate生成的过滤IQueryable可以直接被转译为合法的CosmosDB SQL语句,比如字典索引器访问p.Specific["shoeSize"]可以被正常转译为嵌套文档路径c.specific.shoeSize。
如果遇到转译失败的场景,你可以在两个环节接管逻辑:
- HotChocolate过滤层拦截:自定义实现
IQueryableFilterProvider,重写表达式生成逻辑,针对动态字段按照你预设的规则生成符合CosmosDB要求的表达式 - 数据访问层拦截:在执行查询前拿到HotChocolate生成的IQueryable对象,通过自定义表达式树访问器重写不符合要求的表达式节点,或者直接解析过滤参数,手动拼接CosmosDB参数化查询语句
内容的提问来源于stack exchange,提问作者Cowborg
相关产品推荐
相关产品推荐

