0
votes

How to create a lambda function to update a new record on amplify project using GraphQL ?

I have an amplify project using api GraphQL as api (also dynamoDB).

My app is a simple todo list, just to study, so I'm saving todos on my dynamoDB, that's my schema:

type Todo @model @auth(rules: [{ allow: owner }]) {
    id: ID!
    title: String!
    status: String
}

When I create a new Todo I only set the title, not the status, I want to update the status with a default value using a lambda trigger function (I know I don't have to do that way, but I'm trying that to learn more lambda functions on amplify).

So I followed the steps from amplify docs, but now I can't figure it out what's the next step (I'm not familiar with aws lambda functions).

What I want to do something like:

for each new record
newRecord.status = 'To do'
newRecord.update()
1

1 Answers

1
votes

When you first create the Todo item, it is stored as an item in a DynamodDB table. To update the todo item, you need to update the item in the DynamoDB table.

When you're updating an item in DynamoDB you need to use an AWS SDK to handle this. The simplest sdk to use is to use the AWS DynamoDB Document Client if you are using nodejs in the lambda function.

// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set the region
AWS.config.update({region: 'REGION'}); //replace Region with the region you are using ('EU-WEST-1')

// Create DynamoDB document client
var docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});


// put the the following code in the exports.handler in your lambda function
var params = {
  TableName: 'Todo-SOMERANDOMSTRING-ENV',//The name of your dynamodb table
  Key: {
    'id' : 'asasd123-asdsa1-12sdasads-12', // the id of your todo item
  },
  UpdateExpression: 'set status = :s',
  ExpressionAttributeValues: {
    ':s' : 'To do' // what the new status should be
  }
};
// and run the update function
docClient.update(params, function(err, data) {
  if (err) {
    console.log("Error", err);
  } else {
    console.log("Success", data);
  }
});

Edit

Based on your comment I think you might be on the DynamoDB Lambda Triggers section (?) and your boilerplate lambda function might looks like this:

exports.handler = function (event, context) {
  console.log(JSON.stringify(event, null, 2));
  event.Records.forEach((record) => {
    console.log(record.eventID);
    console.log(record.eventName);
    console.log('DynamoDB Record: %j', record.dynamodb);
  });
  context.done(null, 'Successfully processed DynamoDB record');
};

I haven't done this type of trigger myself before so I'm not completely sure how data in record is structured, but I think it might will be accessible like this:

record.data.id
//or
record.Item.id

You can find this out by going to the lambda console, find and open your lambda function, go to "monitoring" and then open "View logs in CloudWatch" in AWS and check the CloudWatch logs after you have created an item.

Assuming it is record.Item.id your lambda code could look like this (untested):

var AWS = require('aws-sdk');
AWS.config.update({region: 'REGION'});
var docClient = new AWS.DynamoDB.DocumentClient({apiVersion: '2012-08-10'});

exports.handler = function (event, context) {
  console.log(JSON.stringify(event, null, 2));
     event.Records.forEach((record) => {
        var params = {
           TableName: 'YOUR-DB-TABLE-NAME',
           Key: {
              'id' : record.Item.id,
           },
           UpdateExpression: 'set status = :status',
           ExpressionAttributeValues: {
              ':status' : 'To do' // what the new status should be
           }
        };
        docClient.update(params, function(err, data) {
           if (err) {
              console.log("Error", err);
           } else {
              console.log("Success", data);
           }
        });
      });
   context.done(null, 'Successfully processed DynamoDB record');
 };

I don't think this code is entirely complete, and you might have to change how/when the "context.done" function works (because I think it will run before the code finishes updating the item), but it might get you somewhat in the right direction.