0

GraphQL サーバーとして sangria を使用しています。スキーマの関連部分は次のとおりです。

  val Account =
    ObjectType(
      "Account",
      "An account with a municipal unit",
      fields[Unit, Account](
        Field("id", StringType, Some("The account id"), resolve = _.value.id),
        Field("mu", OptionType(MunicipalUnit), Some("The municipal unit this account is with"), resolve = ctx => ctx.ctx.asInstanceOf[ObjectResolver].resolve[MunicipalUnit](ctx.value.mu)),
        Field("eu", OptionType(EconomicUnit), Some("The economic unit this account belongs to"), resolve = ctx => ctx.ctx.asInstanceOf[ObjectResolver].resolve[EconomicUnit](ctx.value.eu)),
        Field("location", OptionType(Location), Some("The physical location associated with this account"), resolve = ctx => ctx.ctx.asInstanceOf[ObjectResolver].resolve[Location](ctx.value.location)),
        Field("amountDue", BigDecimalType, Some("The amount currently due"), resolve = _.value.amountDue)
      ))

  val Citizen =
    ObjectType(
      "Citizen",
      "A Citizen",
      interfaces[Unit, Citizen](EconomicUnit),
      fields[Unit, Citizen](
        Field("id", StringType, Some("The ID of the citizen"), resolve = _.value.id),
        Field("name", StringType, Some("The name of the citizen"), resolve = _.value.id),
        Field("delegates", OptionType(ListType(OptionType(EconomicUnit))), Some("The delegates of the citizen"), resolve = ctx => DeferDelegates(ctx.value.delegates)),
        Field("locations", OptionType(ListType(OptionType(Location))), Some("The locations of the citizen"), resolve = ctx => DeferLocations(ctx.value.locations)),
        Field("accounts", OptionType(ListType(OptionType(Account))), Some("The accounts of the citizen"), resolve = ctx => DeferAccounts(ctx.value.accounts))
      )
    )

延期コードは

  def resolveByType[T](ids: List[Any])(implicit m: Manifest[T]) = ids map (id => resolver.resolve[T](id))

  override def resolve(deferred: Vector[Deferred[Any]], ctx: Any) = deferred flatMap {
    case DeferAccounts(ids) => resolveByType[Account](ids)
    case DeferLocations(ids) => resolveByType[Location](ids)
    case DeferDelegates(ids) => resolveByType[EconomicUnit](ids)
    case DeferMUs(ids) => resolveByType[MunicipalUnit](ids)

    case _ =>
      List(Future.fromTry(Try(List[Any]())))
  }

個々のオブジェクトに対してすべてが機能しますが、オブジェクトとその子をリクエストしようとすると、返される子は 1 つだけです

クエリ:

{
    citizen(id: "12345") {
    name
    accounts {
      id
      amountDue
    }
  }
}

応答:

{
  "data": {
    "citizen": {
      "name": "12345",
      "accounts": [
        {
          "id": "12345",
          "amountDue": 12.34
        }
      ]
    }
  }
}

その通りです。リストのすべての要素がロードされていることをバックエンドで確認できますが、返されていないようです。

4

1 に答える 1

2

問題はflatMap、無関係なリストのすべての要素を使用して、結果のリストにマージしていることです。

これらの小さな変更により、望ましい結果が得られると思います。

def resolveByType[T](ids: List[Any])(implicit m: Manifest[T]): Future[Seq[T]] = 
  Future.sequence(ids map (id => resolver.resolve[T](id)))

override def resolve(deferred: Vector[Deferred[Any]], ctx: Any) = deferred map {
  case DeferAccounts(ids) => resolveByType[Account](ids)
  case DeferLocations(ids) => resolveByType[Location](ids)
  case DeferDelegates(ids) => resolveByType[EconomicUnit](ids)
  case DeferMUs(ids) => resolveByType[MunicipalUnit](ids)

  case _ =>
    List(Future.fromTry(Try(List[Any]())))
}

ベクトルのすべてDeferredの値に対して、結果のリストにdeferred単一Futureの要素が 1 つだけ存在することを確認するためにインポートされます (リスト内の同じ位置にある必要があります)。

resolveこれはパフォーマンスのために最適化された非常に低レベルの API であるため、メソッドのシグネチャにはあまり型安全性がありません。この場合のエラー報告を改善するための問題を作成しました

于 2016-08-12T12:03:52.303 に答える