Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GraphQL.NET: How to separate the root query into multiple parts

I currently have a small application which is using GraphQL to communicate with the .net core backend. I currently have one one root query as is mandatory for GraphQL and am looking for a way to break this up into multiple pieces for organization's sake. My Query looks as follows:

public class ReactToFactsQuery : ObjectGraphType
{
    public ReactToFactsQuery(IArticleService articleService,
        INewsItemService newsItemService)
    {
        Field<ArticleType>(
            name: "article",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context =>
            {
                var id = context.GetArgument<int>("id");
                return articleService.Get(id);
            }
        );

        Field<ListGraphType<ArticleType>>(
            name: "articles",
            arguments: new QueryArguments(new QueryArgument<IntGraphType>() { Name = "count" }),
            resolve: context =>
            {
                var count = context.GetArgument<int?>("count");
                if (count.HasValue)
                {
                    return articleService.GetAll(count.Value);
                }
                else
                {
                    return articleService.GetAll();
                }

            }
        );

        Field<ListGraphType<NewsItemType>>(
            name: "newsItems",
            arguments: new QueryArguments(
                new QueryArgument<IntGraphType>() { Name = "count" },
                new QueryArgument<IntGraphType>() { Name = "newsType" }),
            resolve: context =>
            {
                var count = context.GetArgument<int?>("count");
                var category = context.GetArgument<int>("newsType");
                var newsType = (NewsType)category;

                if (count.HasValue)
                {
                    return newsItemService.GetMostRecent(newsType, count.Value);
                }
                else
                {
                    return newsItemService.GetMostRecent(newsType);
                }
            }
        );
    }
}

Currently the query is pretty small and manageable but as the application grows, I can easily see there being a huge number of queries defined in this class. THe current query names that exist are article, articles, and newsItems. Preferably, I'd like to create a query class to represent each model type (i.e one query class for article related queries, one for news item related queries, etc).

I've read the documentation here however I for whatever reason am struggling to understand the example here and how to apply it to my code.

All help is appreciated.

like image 544
GregH Avatar asked Mar 15 '19 18:03

GregH


1 Answers

As the documentation says, you can split queries into virtual groups like this ...

Creating sub query types (ArticlesQueryType) that controls the specific queries.

public class RootQuery : ObjectGraphType
{
    public RootQuery()
    {
        Name = "RootQuery";
        // defines the articles sub query and returns an empty anonymous type object
        // whose only purpose is to allow making queries on the subtype (ArticlesQueryType)
        Field<ArticlesQueryType>("articles", resolve: context => new {});
    }
}

// defines the articles specific queries
public class ArticlesQueryType: ObjectGraphType
{
    public ArticlesQueryType(IArticleService articleService)
    {
        Name = "ArticlesQuery";
        Field<ArticleType>(
            name: "article",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context =>
        {
            var id = context.GetArgument<int>("id");
            return articleService.Get(id);
        });
    }
}

GraphQL query type would be

type RootQuery {
  articles: ArticlesQuery
  news: NewsQuery
}

type ArticlesQuery {
   article(id: ID): Article
   articles: [Article]
}
...

On the other hand, if you don't want to change the query structure and has only one root that holds the specific queries, you can split the queries into partial classes for clarity ...

public partial class RootQuery: ObjectGraphType
{
    private IArticleService ArticleService { get; }

    public RootQuery()
    {
        Name = "RootQuery";

        InitializeArticlesQueries()
    }
}

and in another file (RootQuery_Articles.cs) for example

public partial class RootQuery
{
    protected InitializeArticlesQuery()
    {
        Field<ArticleType>(
            name: "article",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context =>
        {
            var id = context.GetArgument<int>("id");
            return articleService.Get(id);
        });
    }
}

This way, the GraphQL query type is

type RootQuery {
    articles: [Article]
    ....
}
like image 112
jgoday Avatar answered Oct 25 '22 08:10

jgoday