Grant
Grant

Reputation: 849

How to allow Optional Key in API Gateway mapping template

I have an API gateway that scans a DynamoDB table. I want to pass LastEvaluatedKey in my request body; if I pass a LastEvaluatedKey then the everything works and I get a response with the expected data - so I'm half way there.

But, of course, the first time I send a request to the API LastEvaluatedKey will not exist, so the ExclusiveStartKey in the mapping template that expects a LastEvaluatedKey must be optional. I've tried a few different ways to get this to be optional but nothing has worked so far. Here is what I have:

#set($hasName = $input.json('$.Name'))
{
    "TableName": "MyTable",
    #if($hasName && $hasName.length() != 0)
    "ExclusiveStartKey": {
        "Name": {
            "S": $input.json('$.Name')
        },
        "Date": {
            "S": $input.json('$.Date')
        }
    },#end
    "FilterExpression": "begins_with(#dt, :tdt)",
    "ExpressionAttributeNames": {
        "#dt": "Date"
    },
    "ExpressionAttributeValues": {
        ":tdt": {
            "S": "$input.params('date')"
        }
    }
}

As I say, the above works when I do pass a LastEvaluatedKey in my request body, but when I do not I get the error:

{
    "__type": "com.amazon.coral.validate#ValidationException",
    "message": "The provided starting key is invalid: One or more parameter values were invalid: An AttributeValue may not contain an empty string"
}

...it's still expected the LastEvaluatedKey

I've also tried wrapping Name and Date inside if #if but with no luck at all. I've taken inspiration from other answers such as: this and this, but no luck.

Upvotes: 4

Views: 1838

Answers (2)

SGT_RAGEQUIT
SGT_RAGEQUIT

Reputation: 36

In my example cursor is the LastEvaluatedKey:

#set($hasCursor = $input.params('cursor') != "")
{
    "TableName": "my-table"
    #if($hasCursor) "ExclusiveStartKey":$util.base64Decode("$input.params('cursor')")
    #end
}

It just checks if cursor is passed as a query param (like /my/api?cursor=myencodedlastevaluatedkey), and only adds ExclusiveStartKey to the request if it is.

Upvotes: 2

Leopoldo Varela
Leopoldo Varela

Reputation: 364

If you know beforehand that both keys are string type, you can do:

#set($Name = $input.params('Name'))
#set($Date = $input.params('Date'))
{
#if($Name != '' && $Date != '')
  "ExclusiveStartKey": {
    "Name": {
      "S": "$Name"
    },
    "Date": {
      "S": "$Date"
    }
  },
#end
#if($Date != '')
  "FilterExpression": "begins_with(#dt, :tdt)",
    "ExpressionAttributeNames": {
        "#dt": "Date"
    },
    "ExpressionAttributeValues": {
        ":tdt": {
            "S": "$Date"
        }
    }
  },
#end
  "TableName": "MyTable"
}

This makes the filter optional, only if Date is passed as argument

Upvotes: 1

Related Questions