HotChocolate Schema Stitching时过滤输入类型重复注册求助
解决HotChocolate Schema Stitching中过滤类型重复注册的问题
问题根源
主、次级服务各自启用了AddFiltering(),都会生成StringOperationFilterInput这类通用过滤输入类型,Schema合并时因为类型名称完全重复,导致注册冲突报错。
方案一:合并同名过滤类型(推荐)
利用HotChocolate的Schema合并能力,对两个Schema中结构完全一致的同名过滤类型进行合并,既保留两边的过滤功能,又避免冲突。
修改主项目的Program.cs,在添加远程Schema时配置类型合并规则:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddHttpClient("Movies", c => c.BaseAddress = new Uri("https://localhost:7001/graphql")); builder.Services.AddGraphQLServer() .AddQueryType<Query>() .AddRemoteSchema("Movies", ignoreRootTypes: true, configure: schema => { schema.TypeMergeHandler((leftType, rightType) => { // 匹配所有过滤操作输入类型,合并同名且结构一致的类型 if (leftType.Name.EndsWith("OperationFilterInput") && leftType.Name == rightType.Name && leftType.Kind == TypeKind.InputObject && rightType.Kind == TypeKind.InputObject) { return TypeMerge.Merge(leftType, rightType); } return TypeMerge.KeepLeft; }); }) .AddTypeExtensionsFromFile("./Stitching.graphql") .AddFiltering(); var app = builder.Build(); app.MapGraphQL(); app.Run();
方案二:为次级服务的过滤类型加前缀
给次级服务生成的过滤输入类型添加专属前缀,让它和主服务的类型名称区分开。
修改次级项目的Program.cs:
var builder = WebApplication.CreateBuilder(args); builder.WebHost.UseUrls("https://localhost:7001/"); builder.Services.AddGraphQLServer() .AddQueryType<Query>() .AddFiltering(options => { // 为过滤类型添加"Movie"前缀 options.AddConvention<IFilterConvention>(new FilterConvention { OperationName = typeName => $"Movie{typeName}" }); }); var app = builder.Build(); app.MapGraphQL(); app.Run();
此时次级服务的过滤类型会变成MovieStringOperationFilterInput,和主服务的StringOperationFilterInput不再重名。如果需要在主服务端使用次级服务的过滤能力,需确保查询参数能正确映射到次级服务的类型。
方案三:主服务统一处理过滤
如果次级服务的数据量不大,可让主服务接管所有过滤逻辑,次级服务仅返回原始数据。
- 修改次级项目的
Query类,移除[UseFiltering]特性:
public class Query { public IEnumerable<Movie> GetMovie() => new[] { new Movie("Die Hard") }; }
- 修改次级项目的服务配置,移除
AddFiltering():
builder.Services.AddGraphQLServer() .AddQueryType<Query>();
- 修改主项目的
Stitching.graphql,给movies字段添加@useFiltering,由主服务本地处理过滤:
extend type Query { movies: [Movie!]! @delegate(schema: "Movies", path:"movie") @useFiltering }
这种方式适合小数据量场景,主服务会先拉取所有Movies数据,再在本地应用过滤规则。
内容的提问来源于stack exchange,提问作者Orion
相关产品推荐
相关产品推荐

