GraphQL 将 @include 逻辑传递给存储库调用

GraphQL pass @include logic to the repository call

我有一个问题

{
    "query": "query($withComments: Boolean!) {feed(id: 2) {name comments @include(if: $withComments) {title text}}}",
    "vars": {"withComments": true}
}

基于 withComments 变量,我可以抓取带或不带评论的提要。有用。但似乎 Sangria 在任何情况下都必须获得带有评论的提要(对我来说性能问题是什么)即使我不需要它们并通过 withCommentsfalse 值:

val QueryType = ObjectType(
    "Query",
    fields[GraphQLContext, Unit](
      Field("feed", OptionType(FeedType),
        arguments = Argument("id", IntType) :: Nil,
        resolve = c => c.ctx.feedRepository.get(c.arg[Int]("id")))))

include/exclude 继承对象中的列表(比如关系)的正确方法是什么,如果我不 @include,则不要 select 存储库中的所有数据,使一个知道它的存储库?

如果解决方案是进行两个查询 feedfeedWithComments 我看不到 @include 的任何灵活性。

由于您的数据访问对象 (resository) 和 GraphQL 模式彼此分离,因此您需要显式传播有关特定字段 inclusion/exclusion 的信息。

有多种方法可以解决这个问题,但我认为最简单的方法是使用 projections。在您的情况下,它可能看起来像这样:

val IdArg = Argument("id", IntType)

val QueryType = ObjectType(
  "Query",
  fields[GraphQLContext, Unit](
    Field("feed", OptionType(FeedType),
      arguments = IdArg :: Nil,
      resolve = Projector(1, (c, projection) ⇒
        if (projection.exists(_.name == "comments"))
          c.ctx.feedRepository.getWithComments(c arg IdArg)
        else
          c.ctx.feedRepository.getWithoutComments(c arg IdArg)))))

使用 Projector 我要求图书馆给我嵌套字段的 1 级深度投影(只是字段名称)。然后根据这个信息我可以用不同的方式获取数据(有或没有评论)