3

This is my first time working with VTL, so please correct my code if there is something very silly in it.

What I want to achieve

{
    "cities": ["jaipur", "mumbai", "delhi", "sheros", "jalandhar", "bengaluru"]
}

Graphql schema:

type Query{
  getCitiesForGroups: String
}

Default response template:

#if($ctx.error)
    $utils.error($ctx.error.message, $ctx.error.type)
#end
    $utils.toJson($utils.rds.toJsonObject($ctx.result)[0])

Using the default response template, the result I was getting

{ "data": { "getCitiesForGroups": [ "{groupcity=jaipur}", "{groupcity=mumbai}", "{groupcity=delhi}", "{groupcity=sheros}", "{groupcity=jalandhar}", "{groupcity=bengaluru}" ] } }

My request template

{
    "version": "2018-05-29",
    "statements": [
        "select DISTINCT LOWER(city) as city from public.Groups"
    ]
}

To get the desired output, I changed the response template as I wanted to loop over the response I got from the DB, and remove the {city=} from the string by using the substring method given in AWS resolver mapping docs and this is where I am facing the problem.

My response template

#if($ctx.error)
    $utils.error($ctx.error.message, $ctx.error.type)
#end
#set ($rawListOfCities = $utils.rds.toJsonObject($ctx.result)[0])
#set ($sanitisedListOfCities = [])
#foreach( $city in $rawListOfCities )
    #set ($equalToIndex = $city.indexOf("="))
    #set ($equalToIndex = $equalToIndex + 1)
    #set ($curlyLastIndex = $city.lastIndexOf("}"))
    #set ($tempCity = $city.substring($equalToIndex, $curlyLastIndex))
    ## #set ($tempCity = $city)
    $util.qr($sanitisedListOfCities.add($tempCity))
#end
$util.toJson($sanitisedListOfCities)

The response that I am getting:

{
  "data": {
    "getCitiesForGroups": "[null, null, null, null, null, null]"
  }
}

However, when I use the line #set ($tempCity = $city) and comment out the line above it, I get the following response:

{
  "data": {
    "getCitiesForGroups": "[{city=jaipur}, {city=mumbai}, {city=delhi}, {city=sheros}, {city=jalandhar}, {city=bengaluru}]"
  }
}

Which means $city has the value {city=jaipur}, so which I want to sanitize and add it to ($sanitisedListOfCities) and return it as the response.

But I am getting null as the result substring method.

So how can I sanitize the response from DB and return it?

Sajal
  • 89
  • 1
  • 14

1 Answers1

4

I had a similar issue and this is how I solved it.

First, your Graphql schema should look like,

type Query {
    getCitiesForGroups: cityList
}

type cityList {
    cities: [String]
}

Your request mapping template,

{
    "version": "2018-05-29",
    "statements": [
        "select DISTINCT LOWER(city) as city from public.Groups"
    ]
}

And finally your response mapping template

#set($cityList = [])
#set($resMap = {})
#if($ctx.error)
    $utils.error($ctx.error.message, $ctx.error.type)
#end

#foreach($item in $utils.rds.toJsonObject($ctx.result)[0])
    $util.qr($cityList.add($item.city))
#end
$util.qr($resMap.put("cities", $cityList))

#return($resMap)

Expected response(complete)

{
  "data": {
    "getCitiesForGroups": {
      "cities": [
        "jaipur",
        "mumbai",
        "delhi",
        "sheros",
        "jalandhar",
        "bengaluru"
      ]
    }
  }
}

I hope this helps you.

Myz
  • 818
  • 1
  • 8
  • 21
  • Your solution works like a charm. Thank you so much for helping out. Can you please point me to some resources so I can understand this all much better? Thank you once again. – Sajal May 14 '20 at 19:11
  • Glad to help you. I usually refer to AWS Developer Guide, Stackoverflow and sometimes AWS Discussion forum. Other than that, Adrian Hall and Nader Dabit have some amazing tutorials and guides on AppSync; you should also check them out! – Myz May 15 '20 at 03:12