AWS API gateway body mapping template for dynamodb map

匿名 (未验证) 提交于 2019-12-03 01:34:02

问题:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!