5

我正在通过 Sangria GraphQL("org.sangria-graphql" %% "sangria" % "1.0.0-RC5") 构建 GrapQL 服务器

我不确定正常情况下是否需要它。但是为了提高性能,我想在解析过程中从客户端获取请求的字段。

例如,

如果你要求,

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。可能存在比我尝试的更好的方法。购买以了解请求的字段有利于处理数据。

如果你以某种方式知道,请告诉我。

谢谢你。

4

1 回答 1

4

Sangria 提供了一些功能,可以在您描述的场景中为您提供帮助。

首先是预测:http ://sangria-graphql.org/learn/#projections

当您使用它时,这些字段将被自动收集并作为带有文件名的树形式的参数提供给解析函数。文档本身没有示例,因此我建议您检查这些测试以了解其在实践中的工作方式:https ://github.com/sangria-graphql/sangria/blob/master/src/test/斯卡拉/桑格利亚汽酒/执行/ProjectorSpec.scala

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

于 2017-01-05T23:35:33.500 回答