-1

I have the below piece of code that I try to use to fetch a row of data using values for 3 columns.

const client = new DynamoDB({region: "us-east-1"});
const params = {
TableName: Tables.TYPES,
ExpressionAttributeNames: {
    '#type': "type",
    '#region': "region",
    '#dock': "dock"
},
ExpressionAttributeValues: {
    ":type": type,
    ":dock": dock,
    ":region": region
 },
 KeyConditionExpression: '#type = :type AND #dock = :dock AND #region = :region'
 }
 let types: Record<string, NativeAttributeValue> = data = await client.send(new QueryCommand(params));
 console.log("Received data ", data);

However when I run the above code I get the following error.

"errorMessage": "Cannot read properties of undefined (reading '0')"

What am I doing wrong here? How can I read the row using values for multiple columns in my Dynamo DB table? I am using @aws-sdk/client-dynamodb by the way. Appreciate any help.

UPDATE: Still not working:

const params = {
            TableName: Tables. TYPES,
            FilterExpression: 'type = :type AND dock = :dock AND region = :region',
            ExpressionAttributeValues: {
                ":type": {S: type},
                ":dock": {S: dock},
                ":region": {s: region}
            }
        }
AnOldSoul
  • 4,017
  • 12
  • 57
  • 118
  • 2
    You can have one partition / hash and optionally one range / sort key. You cannot query based on three columns. – luk2302 Jan 24 '23 at 18:22
  • You can use a FilterExpression on the non-key attribute(s). – jarmod Jan 24 '23 at 18:29
  • @jarmod do I have to use ScanCommand with FilterExpression then? – AnOldSoul Jan 24 '23 at 18:35
  • No, and you generally want to avoid scans, of course. Server-side [filters](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/interfaces/querycommandinput.html#filterexpression) are available on queries. – jarmod Jan 24 '23 at 18:36
  • BTW you passed `params` to the `QueryCommand` constructor but `params` is undefined (at least in the code I see), which is likely what's causing the runtime error. – jarmod Jan 24 '23 at 18:39
  • @jarmod updated the code with FilterExpression but still getting the same error. `params` was actually a copy paste error, apologies. – AnOldSoul Jan 24 '23 at 18:47
  • You've converted the 3-attribute key condition expression into a 3-attribute filter expression, which is not a valid query. I'm assuming that 1 or 2 of those attributes are keys (pk and optionally sk). You need both key condition and filter expressions. Include the key attributes in the former, and the non-key attributes in the latter. – jarmod Jan 24 '23 at 19:08
  • @AnOldSoul - could you clarify which keys are in your Primary key? – Chris Anderson Jan 24 '23 at 19:13
  • All my columns are non-unique and therefore I ended up using a Guid for partition key. Can I only use a sort key for KeyConditionExpression? – AnOldSoul Jan 24 '23 at 20:57

1 Answers1

2

KeyConditionExpression is for keys only, your partition key and sort key. Outside of that, if you wish to filter on non key attributes you must use FilterExpression.

Assuming type is your Partition key, the params would look like this (edit further to suit your specific needs):

const params = {
TableName: Tables.TYPES,
ExpressionAttributeNames: {
    '#type': "type",
    '#region': "region",
    '#dock': "dock"
},
ExpressionAttributeValues: {
    ":type": type,
    ":dock": dock,
    ":region": region
 },
 KeyConditionExpression: "#type = :type",
 FilterExpression: "#dock = :dock AND #region = :region"
 }
Leeroy Hannigan
  • 11,409
  • 3
  • 14
  • 31
  • All my columns are non-unique and therefore I ended up using a Guid for partition key. Is there a way to query without using a KeyConditionExpression? – AnOldSoul Jan 24 '23 at 21:41
  • For that you would remove the `KeyConditionExpression` and keep your non key values in `FilterExpression` and use the `Scan` API. A GUID is rarely useful as a partition key in DynamoDB. – Leeroy Hannigan Jan 24 '23 at 22:31