8

I have the following query:

query xxx {
   getSomething(id: "id") {
      field1
      field2
   }
}

Is there any way for me to get field1 and field2 in lambda? For example, to query only those fields in mysql, not get all of them just to be discarded by AppSync later.

I tried logging all the $context in the request mapper VTL file but they are not there. Any ideas? Seems quite stupid to not be able to do that. The only thing I get in lambda is the id argument.

Thanks, Mihai

Mihai Blaga
  • 121
  • 8
  • how your response mapping template looks like. Also have you seen this tutorial? https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html – Vasileios Lekakis Nov 14 '18 at 04:59
  • I'm talking about request, not response. Response template is for modifying the response, I'm interested in getting the fields in the request. – Mihai Blaga Nov 14 '18 at 10:26

3 Answers3

6

AppSync now supports getting the GraphQL Info object. You can get the list of requested columns from the selectionSetList variable.

The layout of the Info object:

{
    "fieldName": "string",
    "parentTypeName": "string",
    "variables": { ... },
    "selectionSetList": ["string"],
    "selectionSetGraphQL": "string"
}

An example passing the selectionSetList property to a lambda resolver:

{
    "version" : "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "arguments": $utils.toJson($ctx.args),
        "selectionSetList": $utils.toJson($ctx.info.selectionSetList),
        "selectionSetGraphQL": $utils.toJson($ctx.info.selectionSetGraphQL)
    }
}

Note: If you are trying to pass the selectionSetList then you need to specifically reference it (like in the example above). The list will not be available if the info object is passed in directly with something like $utils.toJson($ctx.info).

Trisped
  • 5,705
  • 2
  • 45
  • 58
4

It might not be the answer you want to hear, but as you've spotted AppSync simply doesn't make the graphql (fields, or otherwise) available to you.

The only two 'options" I can put to you are:

  • Design your query schema so that you can be more precise with your fetching (e.g. getThingFromTableA and getThingFromTableB rather than just getThing)
  • Use field resolvers for expensive to get fields, and employ nested objects if these are all from the same datasource (e.g. { cheapA, cheapB, expensiveA { expensiveTableAThingA, expensiveTableAThingB }, expensiveB }).

n.b. it isn't that uncommon, for example Apollo doesn't by default either.

thomasmichaelwallace
  • 7,926
  • 1
  • 27
  • 33
  • Yeah, I get it. Thought about using a field resolver but that means another lambda, even if it's the same one, it's another lambda fired up. I wanted to get this done with only one function. Thanks – Mihai Blaga Nov 14 '18 at 10:32
  • It does sound like a useful feature- although I guess that because fields can be nested, have arguments, and such it's quite a complex custom object to express. – thomasmichaelwallace Nov 14 '18 at 10:53
  • This oversight on Appsync’s part is quite frustrating. I can imagine scalar fields, for example, that are computed that I’d want to avoid computing if they weren’t asked for. Using field-level resolvers for those fields means an additional round trips to the data source (e.g. database) along with the serialization of the source/parent result and subsequent deserialization in the sub-query resolvers. It’d be nice to have access to the entire query tree below a given query or field resolver so the lambda has the option of optimizing DB access / result computation. E.g., lacinia does – solussd Aug 27 '19 at 04:00
0

Those fields are in the $context.source object. If you pass the entire $context object to your lambda you'd be able to access those fields in event.source

bwobst
  • 340
  • 3
  • 13