GraphQL Hot Chocolate中List<string>字段的筛选问题求解
问题描述
我通过GraphQL查询某实体,该实体包含一个定义为List<string>的BreadCrumbIds属性,该属性通过HasJsonConversion转换,在数据库中存储为JSON字符串,读取时会解析回列表。
简化实体类代码:
public class Area : Entity<Guid> { public List<string> BreadCrumbIds { get; private set; } = new List<string>(); }
对应的EntityTypeConfiguration配置:
public void Configure(EntityTypeBuilder<Area> builder) { builder.Property(x => x.BreadCrumbIds).HasJsonConversion(); }
我期望通过如下GraphQL查询筛选包含指定ID的实体:
areas(where: {and: [{breadCrumbIds: {contains: "4580473b-cf4b-45d5-8ea2-457015cb0e00"}}]}
但执行时报错:
The specified input object field `contains` does not exist.
我的GraphQL查询Resolver代码如下:
[Authorize] [UseOffsetPaging(IncludeTotalCount = true)] [UseProjection] [UseFiltering] [UseSorting] public IQueryable<Area> GetAreas([Service] Context context) => context.Areas;
请问如何解决该问题,实现筛选出列表包含指定字符串的实体?
解决方法
问题出在GraphQL的UseFiltering默认不支持EF Core通过HasJsonConversion序列化的List<string>类型的contains筛选——自动生成的筛选输入类型里没有这个操作符。以下两种方案可以解决:
方案一:自定义筛选输入类型
- 新建
AreaFilterInput类,继承自FilterInputType<Area>,为BreadCrumbIds添加contains操作:
public class AreaFilterInput : FilterInputType<Area> { protected override void Configure(IFilterInputTypeDescriptor<Area> descriptor) { base.Configure(descriptor); descriptor.Field(x => x.BreadCrumbIds) .AllowContains(); } }
- 在Resolver方法中指定使用这个自定义筛选类型:
[Authorize] [UseOffsetPaging(IncludeTotalCount = true)] [UseProjection] [UseFiltering(typeof(AreaFilterInput))] // 替换默认筛选类型 [UseSorting] public IQueryable<Area> GetAreas([Service] Context context) => context.Areas;
方案二:直接绑定EF Core JSON查询函数
如果方案一的自动转换不生效(比如EF Core无法将contains表达式转为数据库能识别的JSON查询),可以手动指定筛选逻辑,让EF Core生成正确的JSON查询语句:
public class AreaFilterInput : FilterInputType<Area> { protected override void Configure(IFilterInputTypeDescriptor<Area> descriptor) { base.Configure(descriptor); descriptor.Field(x => x.BreadCrumbIds) .AddFilteringOperation("contains", (left, right) => EF.Functions.JsonContains(left, $"[\"{right}\"]")); } }
注意:不同数据库的JSON函数语法有差异,比如SQL Server和PostgreSQL的JsonContains用法不同,需要根据你的数据库类型调整。
完成以上修改后,你的GraphQL查询就能正常筛选出BreadCrumbIds列表包含指定ID的Area实体了。
内容的提问来源于stack exchange,提问作者DaRoGa
相关产品推荐
相关产品推荐

