问题
I am trying to figure out how to insert dynamic data into a dynamodb table via an API Gateway in AWS. Currently I have a dynamodb table and an API endpoint setup that accepts a POST like so.
POST https://{unique-id}.execute-api.us.east-1.amazonaws.com/notification/events
{
"reference_number": 99,
"purchase_date": "1/1/2017"
}
I've setup a body mapping template in the API gateway to massage the data into the dynamodb.
{
"TableName": "Events",
"Item": {
"reference_number": {
"N": "$input.path('$.reference_number')"
},
"purchase_date": {
"S": "$input.path('$.purchase_date')"
}
}
}
The above works and saves to the table.
Suppose I add the event hash to my json (which can change based on events).
{
"reference_number": 99,
"purchase_date": "1/1/2017",
"event": {
"name": "purchase",
"items": [1,3,6],
"info": {
"currencyID": "USD",
"countryID": "US"
}
}
}
How do I save the event attribute to a Map in dynamodb using the API Gateway Body mapping template syntax?
{
"TableName": "Events",
"Item": {
"reference_number": {
"N": "$input.path('$.reference_number')"
},
"purchase_date": {
"S": "$input.path('$.purchase_date')"
},
"event":{
"M": "$input.path('$.event')"
}
}
}
The above template gives me the following error. "Expected map or null"
回答1:
It looks like DynamoDB API actually requires the value of an 'M' attribute to be a Map of String -> AttributeValue. Unfortunately you can't pass the raw JSON. You'll have to manually map the whole event object to make the DDB API happy.
http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_AttributeValue.html#DDB-Type-AttributeValue-M
One possible workaround would be to stringify the event object and write it as type S but that would of course require the reader to expect that behavior.
{
"TableName": "Events",
"Item": {
"reference_number": {
"N": "$input.path('$.reference_number')"
},
"purchase_date": {
"S": "$input.path('$.purchase_date')"
},
"event":{
"S": "$util.escapeJavaScript($input.json('$.event'))"
}
}
}
回答2:
As it seems you finally did. I reckon the best option is to create a simple lambda function between you API and dynamoDB. Leaving the mapping work up to the aws-sdk.
In that case, the body mapping template in the API gateway would be as simple as this:
$input.body
And the function won't be much more complicated. I used a javascript function:
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
var tableName = "tableName";
var saveData = function (data) {
var params = {
TableName: tableName,
Item: data
};
docClient.put(params, function (err, data) {
if (err) {
console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Added item:", JSON.stringify(data, null, 2));
}
});
};
exports.handler = function (event) {
try {
console.log("Processing event: ", event);
saveData(event);
} catch (e) {
console.error("Processed unsuccessfully", e, e.stack);
}
};
http://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/GettingStarted.NodeJs.03.html
回答3:
For my requirement (saving input body), the mapping template is
"rawdata": {
"M": $input.body
}
Note that there are no quotes for input body.
And the data should be in Dynamodb format, for eg
{"username":{"S":"Vishnu"}}
You could use js lib like dynamodb-marshaller to convert json to Dynamodb format. Hope this helps.
来源:https://stackoverflow.com/questions/42078059/aws-api-gateway-body-mapping-template-for-dynamodb-map