【问题标题】:GraphQL + Java - How do I filter subfields?GraphQL + Java - 如何过滤子字段?
【发布时间】:2017-03-08 11:14:56
【问题描述】:

我在我的 Spring 应用程序中使用 graphql-javagraphql-java-annotationsspring-graphql-common 似乎非常有限,并且看起来不再维护),并且我正在努力处理子字段操作。

我想使用 GraphQL 访问两个类 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 以仅选择 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,在A 类中使用以下代码:

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

当我检索到listOfB 时,它确实被调用了。

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

定义不带注释的架构并使用graphql-java 的“经典”方式不是一种选择,因为我的架构非常庞大:/

谢谢:)

【问题讨论】:

  • 您是否尝试将@GraphQLField 与@GraphQLDataFetcher 一起添加到listOfB 字段中?我在这里做了一些测试并且工作了。
  • 哦,是的,很抱歉,它仍然是带有 DataFetcher 的 GraphQLField。但我仍然遇到同样的错误。我设法通过将listOfB 定义为方法而不是字段来使其工作,但它最终变得乏味,所以我目前正在编写自定义注释以允许仅通过添加@GraphQLAnnotation 注释在任何字段上自动过滤就可以了。
  • 我有类似的问题,你能帮帮我吗? stackoverflow.com/questions/66790053/…

标签: java annotations graphql graphql-java


【解决方案1】:

这不是我最终使用的解决方案,因为它不适合我的设计,但您可以这样做:

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,所以您的代码将被复制/粘贴到任何地方,但它仍然有效。

但我找到了一种使用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 参数成为DataFetchingEnvironment 方法中的DataFetchingEnvironment,因此您有一个未调用的空方法,但参数仍传递给您的DataFetcher

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

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

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

【讨论】:

  • 至于今天,该库再次维护,并记录在案。如果您有不明白的地方,请打开一个问题,我们会帮助您
【解决方案2】:

我强烈建议您再次查看这个库,因为它现在又恢复了 维护好了,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
  };

【讨论】:

  • 很好,感谢您的更新。虽然我不再使用 GraphQL 进行项目,所以它现在不会有用,但如果我再次使用 GraphQL,我会确保检查更新:)
猜你喜欢
  • 2020-12-07
  • 2020-04-04
  • 2020-11-07
  • 2021-10-29
  • 2021-02-09
  • 2016-11-07
  • 2018-09-28
  • 2012-10-03
  • 2020-01-16
相关资源
最近更新 更多