1

I'm working on a lambda function that will store information about different users. I have an atribute, userID as my primary partition key, and storedObject as my primary sort key. When I use PutItem, I want it to only add the item if it doesn't already exist in the storedObject attribute.

This is my code

    var params = {
        TableName: 'TrackItDB',
        Item: {
          'userID' : {S: currentUser},
          'storedObject' : {S: itemName},
          'lenderPerson' : {S: personName},
          'objectStatus' : {S: 'lent'},
          'transactionDate': {S: date},
        }
      };
....
const checkIfItemIsStoredParams = {
        Key: {
        "userID" : {
            S: currentUser
        },
        "storedObject" : {
            S: itemName
        }
    },
        TableName: "TrackItDB"
    };
.....
  dynamodb.getItem(checkIfItemIsStoredParams, function(err, data) {

        if (!data) { 
            // no match, add the item
            console.log('Item did not exist, storing to DB');
            console.log(params);
            return dynamodb.putItem(params, function(err, data) {
                if (err) {
                    console.log("Error", err);
                } else {
                    console.log("Success", data);
                }
               });
        }       
        else {
          console.log('Get item succeeded', data);   
              }
        } 
        });

The problem I'm having is that it always outputs Get Item succeeded to the console even if there is no data. I've tried both if (data) and if (!data) and both return the get item succeeded even when there is no data returned.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470

1 Answers1

1

getItem returns an array even if it doesn't find the item you're looking for. Therefore, your conditional statement will always be truthy since you're checking for whether data is null/undefined. You should instead check for the length of data:

if (!data.length) { // item doesn't exit
    // put new item
}

An alternative solution would be to simplify what you're trying to do by making a single call to DynamoDB instead of two. This might be a good idea if you're worried about performance or AWS usage costs. putItem has the parameter ConditionExpression which allows you to have fine-grain control over which items should be updated based on conditions that you specify.

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html

For your case it might look something like this:

var params = {
    TableName: 'TrackItDB',
    Item: {
      'userID' : {S: currentUser},
      'storedObject' : {S: itemName},
      'lenderPerson' : {S: personName},
      'objectStatus' : {S: 'lent'},
      'transactionDate': {S: date},
    },
    ConditionExpression: 'attribute_not_exists(storedObject)'
};

dynamodb.putItem(params, function(err, data) {
    if (err) {
        console.log("Error", err);
    } else {
        console.log("Success", data);
    }
});
putipong
  • 350
  • 1
  • 9
  • 1
    The 'if (!data.length)' did not work, but that's OK the conditionExpression does and as you stated is the much better way to do. Thank you for your help. – James Gaudet Nov 02 '18 at 18:00