【问题标题】:Combine multiple deferred values into a new deferred type in Sangria, GraphQL Implementation在 Sangria 中将多个延迟值组合成一个新的延迟类型,GraphQL 实现
【发布时间】:2019-01-03 04:35:33
【问题描述】:

我们有两个端点(后端调用),它们返回不同但相关的数据类型 XDataYData。如果XData 的实例存在id 为1,那么一定有YData 的实例具有相同的id 为1

我们为xFetcheryFetcher 的每种数据类型创建了一个提取器。这些提取器在我们的 GraphQL 查询中单独使用以从两个端点获取数据,但对于某些用例,我们希望使用特定 id 组合从它们两者检索到的数据,例如,1。这种组合可能不是简单的列表追加,如下例所示。

由于XDataYData 在查询的其他部分也被单独查询,我们不能简单地将这两个解析器合并为一个,并且尽可能避免对同一个端点进行多次调用。

我为此用例创建了一个简化示例。我们如何返回一个延迟值,结合从两个 fetcher 检索到的数据?

case class Ctx()
case class XData(id: Int, a: Seq[String], b: String)
case class YData(id: Int, a: Seq[String], c: String)
case class Data(id: Int)

val xFetcher = Fetcher((ctx: Ctx, ids: Seq[Int]) => Future {
  ids.map(id => XData(1, Seq.empty, "")) // Back end call to (endpoint X)
})(HasId(_.id))

val yFetcher = Fetcher((ctx: Ctx, ids: Seq[Int]) => Future {
  ids.map(id => YData(1, Seq.empty, "")) // Back end call to (endpoint Y)
})(HasId(_.id))

val GData = deriveObjectType[Ctx, Data](
  AddFields(
    Field("a",
      ListType(StringType),
      resolve = ctx => getA(ctx))
  )
)

def getA(ctx: Context[Ctx, Data]) = {
  val id = ctx.value.id

  // Here I should also get an instance of `YData` and return the
  // combination of the sequences `a` in both instances (xData, yData)
  val xData: XData = ??? //getDeferredXData()
  val yData: YData = ??? //getDeferredYData()
  val desiredOutput = xData.a ++ yData.a

  // I can get `a` from one instance but not both of them together
  DeferredValue({
    val xData = xFetcher.defer(id)
    // val yData = yFetcher.defer(id)
    // How can we combine both into one deferred value?
    xData
  }).mapWithErrors { data => (data.a, Vector.empty) }
}

我没怎么用过桑格利亚汽酒,所以请原谅与deferred resolversfetchers相关的任何不清楚的信息

【问题讨论】:

    标签: scala graphql sangria


    【解决方案1】:

    您的场景描述听起来与这个问题非常相似:

    Add additional items to per-request cache

    它已经实现,但尚未发布。

    另外,如果可以始终同时加载XDataYData,那么您可以为元组(XData, YData) 定义一个提取器。然后在解析器中,您可以从元组中提取所需的对象。像这样的:

    DeferredValue(fetcher.defer(id)).map {case (xData, yData) ⇒ xData}
    

    【讨论】:

    • 感谢新功能和您的回复。我认为如果我们在第一次查询时缓存XData,然后在需要YData 时访问此缓存,这可能会有所帮助。在我们的例子中,YData 是在需要时访问的扩展数据,并且这些数据不仅从一个服务中获取,还从另外大约 5 个服务中获取。 XData 非常大并且总是返回,这就是为什么在查询扩展的时候使用它的 fetcher 来减少XData 的服务很重要。如果您认为我应该详细说明并创建一个新问题,请告诉我。
    猜你喜欢
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多