AppSync wrong id for schema in DynamoDB - amazon-web-services

I am using a graphql API with AppSync that receives post requests from a lambda function that is triggered by AWS IoT with sensor data in the following JSON format:
{
"scoredata": {
"id": "240",
"distance": 124,
"timestamp": "09:21:11",
"Date": "04/16/2022"
}
}
The lambda function uses this JSON object to perform a post request on the graphql API, and AppSync puts this data in DynamoDB to be stored. My issue is that whenever I parse the JSON object within my lambda function to retrieve the id value, the id value does not match with the id value stored in DynamoDB; appsync is seemingly automatically generating an id.
Here is a screenshot of the request made to the graphql api from cloudwatch:
Here is what DynamoDB is storing:
I would like to know why the id in DynamoDB is shown as 964a3cb2-1d3d-4f1e-a94a-9e4640372963" when the post request id value is "240" and if there is anything I can do to fix this.

I can’t tell for certain but i’m guessing that dynamo db schema is autogenerating the id field on insert and using a uuid as the id type. An alternative would be to introduce a new property like score_id to store this extraneous id.

If you are using amplify most likely the request mapping templates you are generating automatically identify the "id" field as a unique identifier to be generated at runtime.
I recommend you to take a look at your VTL request template, you will most likely find something like this:
$util.qr($context.args.input.put("id", $util.defaultIfNull($ctx.args.input.id, $util.autoId())))
Surely the self-generated id comes from $util.autoId()
Probably some older version of Amplify could omit the verification $util.defaultIfNull($ctx.args.input.id,... and always overwrite the id by self-generating it.

Related

How to Clear a pickup list value in Salesforce while updating from AWS APPFlow

We are trying to push data into a custom SalesForce object using AWS AppFlow, the object is a multi select pickup list and expects 0-* items. The issue is once the value is set through AppFlow the value is not cleared when the property is set to null again. We are mapping the field to an Empty String when we want to clear it.
We have tried setting an Empty XML Tag but sadly that doesn't clear the value in Salesforce
Do you know which Salesforce API this uses behind the scenes?
In SOAP API you pass special fieldsToNull tag. See https://ideas.salesforce.com/s/idea/a0B8W00000GdjWwUAJ/allow-nulls-to-be-passed-as-a-valid-value-via-the-apis?sfdcIFrameOrigin=null and https://developer.salesforce.com/docs/atlas.en-us.238.0.api.meta/api/sforce_api_calls_concepts_core_data_objects.htm?q=fieldstonull
In "normal" (synchronous) REST API should be just a null node in JSON
{
"Id" : "001...",
"Description": null
}
And in bulk REST API... depends. If you pass JSON - same as above. If you pass a CSV - use #N/A.

Return all items or a single item from DynamoDB from AWS API Gateway endpoint

I am using AWS proxy with AWS API Gateway to interact with a DynamoDB table. I have an API resource, under which I have a GET method with the below configuration:
The API uses the Scan action as seen above to fetch all the items from the DynamoDB table. I also have the following request integration mapping template;
{
"TableName": tableName
}
Its really simple. But my problem is that I would like to add another GET method to get each item by their id, which will be supplied in the URL as a param. However, since I have already setup one GET method, I am not able to setup another to fetch only a single item. I am aware I can use mapping templates and Scan as given in the docs to conditionally fetch items if a param is given, but that would mean scanning the entire table, which is a waste each time I want to fetch a single item.
Is there any other way to do this?

AppSync Dynamodb Resolvers

I am trying to learn how to use AppSync and its DynamoDB integrations.
I have successfully created an AppSync GraphQL API and linked a resolver to a getter on the primary key and thought I understood what is happening. However, I can not get a putItem resolver to work at all and am struggling to find a useful way to debug the logic.
There is a cdk repository here which will deploy the app. Lines 133-145 have a hand written schema which I thought should work however that receives the error
One or more parameter values were invalid: Type mismatch for key food_name expected: S actual: NULL (Service: DynamoDb, Status Code: 400
I also have attempted to wrap the expressions in quotes but receive errors.
Where should I go from here?
The example data creates a table with keys
food_name
scientific_name
group
sub_group
with food_name as the primary key.
https://github.com/AG-Labs/AppSyncTask
Today I have attempted to reimplement the list resolver as
{
"version" : "2017-02-28",
"operation" : "Scan",
## Add 'limit' and 'nextToken' arguments to this field in your schema to implement pagination. **
"limit": $util.defaultIfNull(${ctx.args.limit}, 20),
"nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.nextToken, null))
}
with a response mapping of
$util.toJson($ctx.result.items)
In cloud watch I can see a list of results under log type ResponseMapping (albeit not correctly filtered but i'll ignore that for now) but these do not get returned to the querier. That result is simply
{
"data": {
"listGenericFoods": {
"items": null
}
}
}
I don't understand where this is going wrong.
The problem was that the resolvers were nested.
Writing a handwritten schema fixed the issue but resulted in a poorer API. Going back a few steps and will implement from the ground up slowly adding more resolvers.
The CloudWatch Logs once turned on helped somewhat but still required a lot of changing the resolvers ever so slightly and retrying.

Get all items in DynamoDB with API Gateway's Mapping Template

Is there a simple way to retrieve all items from a DynamoDB table using a mapping template in an API Gateway endpoint? I usually use a lambda to process the data before returning it but this is such a simple task that a Lambda seems like an overkill.
I have a table that contains data with the following format:
roleAttributeName roleHierarchyLevel roleIsActive roleName
"admin" 99 true "Admin"
"director" 90 true "Director"
"areaManager" 80 false "Area Manager"
I'm happy with getting the data, doesn't matter the representation as I can later transform it further down in my code.
I've been looking around but all tutorials explain how to get specific bits of data through queries and params like roles/{roleAttributeName} but I just want to hit roles/ and get all items.
All you need to do is
create a resource (without curly braces since we dont need a particular item)
create a get method
use Scan instead of Query in Action while configuring the integration request.
Configurations as follows :
enter image description here
now try test...you should get the response.
to try it out on postman deploy the api first and then use the provided link into postman followed by your resource name.
API Gateway allows you to Proxy DynamoDB as a service. Here you have an interesting tutorial on how to do it (you can ignore the part related to index to make it work).
To retrieve all the items from a table, you can use Scan as the action in API Gateway. Keep in mind that DynamoDB limits the query sizes to 1MB either for Scan and Query actions.
You can also limit your own query before it is automatically done by using the Limit parameter.
AWS DynamoDB Scan Reference

How to store chat-conversation of chatbot(in aws lex) in DynamoDB

I am building a chatbot for a website that has lots of traffic
I decided to build chatbot in AWS lex
I want to save all chat conversation an single attribute in Dynamo DB for that I had chosen list data type for that attribute
and I am able to get all the slot data into different variables but how to save user entered utterance and prompts that we defined in lex console and how to arrange them like a conversation.
If is there any alternative for storing chat conversation?
Since it's your bot, you know the session timeout value. In your lambda function you can generate a session id (random UUID) and put that in session attribute (read more here). You can create a DDB table in your account and design it like this:
Hash Key: userId
Range Key: sessionId#timeStamp
Request (String attribute): JSON format of request structure that is sent to Lambda function
Now as long as the session is valid you can always retrieve the sessionId that you put in session attributes map. Using this you will always be able to create the range key (sessionId + "#" + currentTimeStamp). In every call that you get in your lambda you also get the user-id for your bot. You can all this information to store the utterances the way you might like.