Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know requested fields in resolver of Object in Sangria GraphQL

Tags:

I am building GrapQL server by Sangria GraphQL("org.sangria-graphql" %% "sangria" % "1.0.0-RC5")

I am not sure it is needed in normally. But to improve performance i'd like to get the requested fields from client during resolving.

For example,

If you request it,

query Query{
  FooObject{
     fieldA
     fieldB
  }
}

Your server may resolve in FooObject object resolver

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

then,

The object field may resolve in field resolver of FooObject object

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

Then, you may get the graphql result

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

What i am trying to do is, during resolving in Object resolver, give field hints like below.

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
}

In this case, I could not find somehow to extract what fields were requested by client in resolver. The Ctx(context) object shows what the The Object is not about the request well in my investigation. Is there some method as i mentioned like Ctx.[__COLLECT_REQUESTED_FIELDS__]() ?

I can try it by each field resolver make a query by select one column in database . But If i could know already what the fields are requested, I can make it in one query and it could solve lot's of N+1 case problem(because top level Object can bring all nested object in a query, it may depends on Database)

I knew there are no best practice for GraphQL still. The better way may exists than i am trying. Buy to know what the fields are requested is good for making processing data.

If you know somehow, let me know it.

Thank you.

like image 950
user2930677 Avatar asked Dec 25 '16 23:12

user2930677


1 Answers

Sangria provides several features that may help you in scenarios you have described.

First is projections: http://sangria-graphql.org/learn/#projections

When you are using it, the fields will be automatically collected and given to resolve function as an argument in form of tree with the filed names. There are no examples in the documentation itself, so I would suggest you to check these tests in order to see how it works in practice: https://github.com/sangria-graphql/sangria/blob/master/src/test/scala/sangria/execution/ProjectorSpec.scala

Regarding N+1 queries issue. I would suggest you to check out a section of the documentation that described deferred value resolution: http://sangria-graphql.org/learn/#deferred-value-resolution. I think it can help you in this respect as well.

like image 181
tenshi Avatar answered Sep 24 '22 16:09

tenshi