2016-08-11 16 views
0

我使用sangria作爲GraphQL服務器。該方案的相關部分是:sangria graphql查詢返回1個元素列表

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]()))) 
    } 

一切工作爲單個對象,但是當我嘗試請求與其子對象,我只得到一個孩子回來

查詢:

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

響應:

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

所以 - 這是正確的,我可以看到在後端列表中的所有元素都被加載,但他們似乎沒有被返回。

回答

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在結果列表元素(和它應該在列表中的相同位置)。

這是相當低級別的API,針對性能進行了優化,因此resolve方法的簽名中沒有太多類型安全性。我只是created an issue來改善這種情況下的錯誤報告。