GraphQL + Java - 如何过滤子字段?

GraphQL + Java - How do I filter subfields?

我正在使用 graphql-java with graphql-java-annotations in my Spring application (spring-graphql-common 似乎非常有限,看起来它不再维护了),我正在努力处理子字段操作。

我想使用 GraphQL 访问两个 classes AB,它们是:

class A {
    @GraphQLField
    Integer id;
    @GraphQLField
    String name;
    @GraphQLField
    List<B> listOfB;
}

class B {
    @GraphQLField
    Integer id;
    @GraphQLField
    String code;
}

我可以使用以下架构成功查询 A 中的所有字段以及 B 中的字段:

@Component
public class Schema
{
    public GraphQLObjectType aType;
    public GraphQLSchema aSchema;
    public GraphQLObjectType queryType;

    @Autowired
    public Schema(DataFetcher dataFetcher) throws IllegalAccessException, InstantiationException, NoSuchMethodException
    {
        aType = GraphQLAnnotations.object(A.class);

        queryType =
                GraphQLObjectType
                .newObject()
                    .name("QueryType")
                    .field(GraphQLFieldDefinition.newFieldDefinition()
                        .name("a")
                        .type(aType)
                        .argument(GraphQLArgument.newArgument()
                                .name("id")
                                .type(new GraphQLNonNull(Scalars.GraphQLInt))
                                .build())
                        .dataFetcher(dataFetcher)
                        .build())
                    .build();

        aSchema = GraphQLSchema.newSchema()
                .query(queryType)
                .build();
    }
}

我可以通过以下请求成功过滤 a

{
    a(id:5)
    {
        id,
        name,
        listOfB
        {
            code
        }
    }
}

但是当我尝试过滤 listOfB 时,例如仅使用 take 到 select X 条记录,我得到错误 Validation error of type UnknownArgument: Unknown argument take:

{
    a(id:5)
    {
        id,
        name,
        listOfB(take:3)
        {
            code
        }
    }
}

我明白错误的含义,因为我还没有为 A 上的 listOfB 字段声明任何可能的参数,但我不知道如何使用 graphql-java-annotations.

我已经为 listOfB 添加了一个特定的 DataFetcher,使用 class A 中的以下代码:

@GraphQLDataFetcher(BDataFetcher.class)
private List<B> listOfB;

当我检索 listOfB.

时它确实被调用了

您知道我在使用 graphql-java-annotations 时如何向字段添加参数吗?如果没有,是否有任何解决方法?

在没有注释的情况下定义模式并使用 graphql-java 的 "classic" 方式不是一个选项,因为我的模式真的很大 :/

谢谢:)

这不是我最终使用的解决方案,因为它不符合我的设计,但您可以执行以下操作:

public class MyClass
{
    @GraphQLField
    private Integer id;
    private List<String> items;

    @GraphQLField
    public List<String> items(DataFetchingEnvironment environment, @GraphQLName("take") Integer take, @GraphQLName("after") Integer after)
    {
        List<String> items = ((MyClass) environment.getSource()).getItems();

        Integer fromIndex = 0;
        Integer toIndex = items.size();
        if (after != null)
            fromIndex = after + 1;
        if (take != null)
            toIndex = fromIndex + take;

        return items.subList(fromIndex, toIndex);
    }
}

这很糟糕,因为你没有使用 DataFetcher 所以你的代码将 copy/pasted 无处不在,但它仍然有效。

但我找到了一种使用 DataFetcher 的方法,据说这很奇怪,我想这不是对库的正确使用,但谁知道呢:

public class MyClass
{
    @GraphQLField
    private Integer id;
    private List<String> items;

    @GraphQLField
    @GraphQLDataFetcher(MyClassDataFetcher.class)
    public List<String> items(DataFetchingEnvironment environment, @GraphQLName("take") Integer take, @GraphQLName("after") Integer after)
    {
        return null;
    }

}

这将使参数 takeafter 成为 MyClassDataFetcher.get() 方法中的 DataFetchingEnvironment,因此您有一个未被调用的空方法,但参数仍然传递给你的 DataFetcher.

同样,这并不理想,因为我怀疑它的使用方式,但这是使用 DataFetcher 和我知道的参数的唯一方法。

现在,我没有使用这两个解决方案中的任何一个,我最终完全放弃 graphql-annotations 并开发了我自己的带有自定义注释的解决方案,这些注释允许我自动构建模式(不会公开发布,抱歉)。

我不建议使用 graphql-annotations,除非他们有适用于所有用例的文档。

我强烈建议你再看看这个图书馆,因为它现在又回来了 维护了,readme写的很清楚

关于你的问题: 你应该让你的字段 listOfB 像这样:

@GraphQLField
@GraphQLDataFetcher(ListOfBFetcher.class)
List<B> listOfB(int take){return null};

并且在 dataFetcher 中,您可以从 environment 变量中获取 take 参数(通过 enviroment.getArgument("take")

您还可以通过以下方式使该方法成为 dataFetcher 本身:

@GraphQLField
List<B> listOfB(int take, DataFetchingEnvironment environment){
    //return the list of B
  };