You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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筛选——自动生成的筛选输入类型里没有这个操作符。以下两种方案可以解决:

方案一:自定义筛选输入类型

  1. 新建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();
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:15:41