可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.