Home > Blockchain >  AWS: Querying DynamoDB returns null
AWS: Querying DynamoDB returns null

Time:12-09

Newbie here. I'm trying to query a DynamoDB table from a Lambda function using partition and sort key.

My table has 5 columns, with the partition key id (string) and sort key owner (string).

Below is my lambda function. It is returning null.

const AWS = require('aws-sdk');
AWS.config.update({region: process.env.REGION});

const ddb = new AWS.DynamoDB();

exports.handler = async (event, context) => {
  
  const id = event.id;
  const owner = event.owner;
  
  const params = {
    TableName: process.env.TABLE_NAME,
    KeyConditionExpression: "id = :id and owner = :owner",
    ExpressionAttributeValues: {
      ":id": { S: id },
      ":owner": { S: owner },
    }
  };
        
  await ddb.query(params, function(err, data) {
    if (err) {
      return err;
    } else {
      return data;
    }
  });

My test event for the lambda function looks like:

{
  "id": "someID",
  "owner": "someOwner"
}

I do have an item in the DDB table with the partition key id = "someID" and sort key owner = "someOwner".

Why is this function returning null?

CodePudding user response:

one immediate issue I see with the query is "owner" is a reserved DynamoDB keyword. See a list of them here. You'll want to use the ExpressionAttributeNames parameter to substitute "owner" with "#owner".

I'd also suggest using the promise syntax instead of callback functions. When you return from inside function (err, data)..., you're actually returning from the callback function instead of the lambda function (as jarmod, hinted, beat me to it!). Here's how I'd rewrite the query:

try {
  const data = await ddb.query(params).promise();
  // then, you can get the result of the query in data.Items
  console.log(data.Items);
  return data.Items;
} catch (err) {
  console.log(err);
  // return an empty array, or whatever you wish in the case of an error
  return [];
}

One final suggestion is to use the DynamoDB.DocumentClient instead of plain old DynamoDB. That way you don't need to specify the type of your ExpressionAttributeValues. So, params becomes:

const params = {
    TableName: process.env.TABLE_NAME,
    KeyConditionExpression: "id = :id and #owner = :owner",
    ExpressionAttributeValues: {
      ":id": id,
      ":owner": id,
    },
    ExpressionAttributeNames: {
      "#owner": "owner"
    }
  };

Much cleaner!

  • Related