如何知道Sangria GraphQL中对象解析器中的请求字段

时间:2016-12-25 23:21:56

标签: scala graphql sangria

我正在使用Sangria GraphQL构建GrapQL服务器(“org.sangria-graphql”%%“sangria”%“1.0.0-RC5”)

我不确定它是否正常需要。但为了提高性能,我希望在解析期间从客户端获取请求的字段。

例如,

如果您要求,

query Query{
  FooObject{
     fieldA
     fieldB
  }
}

您的服务器可能会在FooObject对象解析器中解析

resolve = Ctx => DB.session
  .query("select fieldA, fieldB, FieldC, FieldD from DATA_TABLE")
  .map(entity => DataObject(entity.fieldA, entity.fieldB)  // By ORM Mapper
)

然后,

对象字段可以在FooObject对象的字段解析器中解析

Field("fieldA", type..., resolve = _.fieldA )
Field("fieldB", type..., resolve = _.fieldB )
Field("fieldC", type..., resolve = _.fieldC )
Field("fieldD", type..., resolve = _.fieldD )

然后,您可以获得graphql结果

{
  data:{
    FooObject:{
      FieldA: "DataA"
      FieldB: "DataB"
    }
  }
}

我想要做的是,在解析对象解析器时,给出如下的字段提示。

resolve = Ctx => {
// Seq(FieldA[], FieldB[])
val requestedFields: Seq[Field[ ... ]] = Ctx.[__COLLECT_REQUESTED_FIELDS__]()

// "FieldA, FieldB"
val fetchingFieldInQuery:String = requestedFields.foldRight("")((acc, nextField) => acc + ", nextField" )

DB.session
   .query(s"select ${fetchingFieldInQuery} from DATA_TABLE")
    .map( entity => DataObject(entity.fieldA, entity.fieldB)) // By ORM Mapper
}

在这种情况下,我无法以某种方式提取解析器中客户端请求的字段。 Ctx(context)对象在我的调查中很好地显示了对象与请求的关系。是否有像我提到的方法Ctx.[__COLLECT_REQUESTED_FIELDS__]()

我可以尝试通过每个字段解析器通过选择数据库中的一列来进行查询。但是,如果我已经知道请求的字段是什么,我可以在一个查询中进行,它可以解决很多N+1案例问题(因为顶级对象可以将所有嵌套对象带入查询中,它可能取决于数据库)

我知道GraphQL还没有最佳做法。 可能存在比我尝试更好的方式。购买以了解所请求的字段对于处理数据是否有用。

如果你知道,请告诉我。

谢谢。

1 个答案:

答案 0 :(得分:3)

Sangria提供了一些功能,可以帮助您完成所描述的场景。

首先是投影:http://sangria-graphql.org/learn/#projections

当您使用它时,将自动收集字段并将其解析为具有字段名称的树形式的参数。文档本身没有示例,因此我建议您检查这些测试,以了解它在实践中的工作原理:https://github.com/sangria-graphql/sangria/blob/master/src/test/scala/sangria/execution/ProjectorSpec.scala

关于N + 1查询问题。我建议您查看描述延迟值解析的文档部分:http://sangria-graphql.org/learn/#deferred-value-resolution。我认为它也可以在这方面帮助你。