链接用于平面查询的graphql Sangria抓取器

链接用于平面查询的graphql Sangria抓取器,graphql,deferred,chaining,sangria,Graphql,Deferred,Chaining,Sangria,如果我绝对需要返回一个平面数据结构,但是一个外部调用的结果是另一个外部调用的输入,我是否可以按照下面的方式链接抓取器 Field("ageRestriction", StringType, resolve = ctx => DeferredValue(genreFetcher.defer(ctx.value.genreId)) .map(genre =>

如果我绝对需要返回一个平面数据结构,但是一个外部调用的结果是另一个外部调用的输入,我是否可以按照下面的方式链接抓取器

Field("ageRestriction",
          StringType,
          resolve = ctx =>
            DeferredValue(genreFetcher.defer(ctx.value.genreId))
              .map(genre =>
                DeferredValue(ageRestrictionFetcher.defer(genre.ageRestrictionId))
                  .map(ageRestriction =>
                    ageRestriction.name)))
简言之,我有一个回购协议,有电话要打

  • 所有的书
  • 用于id列表的类型(id:Int,ageRestrictionId)
  • id列表的年龄限制(id、名称)
  • 但是我被要求查询应该是平面的,所以不是平面的

    books { 
      title // some title
      genre {
        ageRestriction // PG13
      }
    }
    
    但是

    问题是为了查询外部服务的年龄限制,我需要知道类型调用的结果

    我觉得描述我的案例最简单的方法就是粘贴代码

    import sangria.execution.deferred.{Fetcher, HasId}
    import sangria.macros.LiteralGraphQLStringContext
    import sangria.macros.derive._
    import sangria.schema._
    
    import scala.concurrent.{ExecutionContext, Future}
    
    case class Book(title: String, genreId: Int)
    
    case class Genre(id: Int, ageRestrictionId: Int)
    
    case class AgeRestriction(id: Int, name: String)
    
    
    class Repo {
    
      import Repo._
    
      def getAllBooks() = books
    
      def getGenreListById(genreIds: Seq[Int]) = genreIds.map(genres)
    
      def getAgeRestricitonsByIds(ageRestrictionIds: Seq[Int]) = ageRestrictionIds.map(ageRestrictions)
    }
    
    object Repo {
      val books = Seq(
        Book("title1", genreId = 0),
        Book("title2", genreId = 1))
    
      val genres = Map(
        0 -> Genre(id = 0, ageRestrictionId = 10),
        1 -> Genre(id = 1, ageRestrictionId = 11))
    
      val ageRestrictions = Map(
        10 -> AgeRestriction(id = 10, name = "G"),
        11 -> AgeRestriction(id = 11, name = "PG13"))
    }
    
    
    object SchemaDefinition {
      implicit val ec = ExecutionContext.global
    
      val genreFetcher = Fetcher.caching(
        (ctx: Repo, ids: Seq[Int]) =>
          Future.successful(ctx.getGenreListById(ids)))(HasId(_.id))
    
      val ageRestrictionFetcher = Fetcher.caching(
        (ctx: Repo, ids: Seq[Int]) =>
          Future.successful(ctx.getAgeRestricitonsByIds(ids)))(HasId(_.id))
    
      implicit val ageRestrictionType = deriveObjectType[Unit, AgeRestriction]()
    
      val bookType: ObjectType[Unit, Book] =
        ObjectType(
          "Book",
          fields[Unit, Book](
            Field("title",
              StringType,
              resolve = _.value.title),
            Field("ageRestriction",
              StringType,
              resolve = ctx =>
                DeferredValue(genreFetcher.defer(ctx.value.genreId))
                  .map(genre =>
                    DeferredValue(ageRestrictionFetcher.defer(genre.ageRestrictionId))
                      .map(ageRestriction =>
                        ageRestriction.name)))))
    
      val bookQuery = ObjectType(
        "Query", fields[Repo, Unit](
          Field("books", ListType(bookType),
            resolve = ctx => ctx.ctx.getAllBooks)))
    
      val bookSchema = Schema(bookQuery)
      val query =
        graphql"""{
                   books {
                          title
                          ageRestriction
                         }
                  }"""
        val result = Executor.execute(bookSchema, query, new Repo)
        result.foreach(res ⇒ println(res.spaces2))
    }
    
    或者,如果将结果展平是一种反模式,您能帮助我如何推回这一要求吗

    非常感谢

    import sangria.execution.deferred.{Fetcher, HasId}
    import sangria.macros.LiteralGraphQLStringContext
    import sangria.macros.derive._
    import sangria.schema._
    
    import scala.concurrent.{ExecutionContext, Future}
    
    case class Book(title: String, genreId: Int)
    
    case class Genre(id: Int, ageRestrictionId: Int)
    
    case class AgeRestriction(id: Int, name: String)
    
    
    class Repo {
    
      import Repo._
    
      def getAllBooks() = books
    
      def getGenreListById(genreIds: Seq[Int]) = genreIds.map(genres)
    
      def getAgeRestricitonsByIds(ageRestrictionIds: Seq[Int]) = ageRestrictionIds.map(ageRestrictions)
    }
    
    object Repo {
      val books = Seq(
        Book("title1", genreId = 0),
        Book("title2", genreId = 1))
    
      val genres = Map(
        0 -> Genre(id = 0, ageRestrictionId = 10),
        1 -> Genre(id = 1, ageRestrictionId = 11))
    
      val ageRestrictions = Map(
        10 -> AgeRestriction(id = 10, name = "G"),
        11 -> AgeRestriction(id = 11, name = "PG13"))
    }
    
    
    object SchemaDefinition {
      implicit val ec = ExecutionContext.global
    
      val genreFetcher = Fetcher.caching(
        (ctx: Repo, ids: Seq[Int]) =>
          Future.successful(ctx.getGenreListById(ids)))(HasId(_.id))
    
      val ageRestrictionFetcher = Fetcher.caching(
        (ctx: Repo, ids: Seq[Int]) =>
          Future.successful(ctx.getAgeRestricitonsByIds(ids)))(HasId(_.id))
    
      implicit val ageRestrictionType = deriveObjectType[Unit, AgeRestriction]()
    
      val bookType: ObjectType[Unit, Book] =
        ObjectType(
          "Book",
          fields[Unit, Book](
            Field("title",
              StringType,
              resolve = _.value.title),
            Field("ageRestriction",
              StringType,
              resolve = ctx =>
                DeferredValue(genreFetcher.defer(ctx.value.genreId))
                  .map(genre =>
                    DeferredValue(ageRestrictionFetcher.defer(genre.ageRestrictionId))
                      .map(ageRestriction =>
                        ageRestriction.name)))))
    
      val bookQuery = ObjectType(
        "Query", fields[Repo, Unit](
          Field("books", ListType(bookType),
            resolve = ctx => ctx.ctx.getAllBooks)))
    
      val bookSchema = Schema(bookQuery)
      val query =
        graphql"""{
                   books {
                          title
                          ageRestriction
                         }
                  }"""
        val result = Executor.execute(bookSchema, query, new Repo)
        result.foreach(res ⇒ println(res.spaces2))
    }