4
votes

I'm pretty new to DynamoDB (NO Sql in general) and I'm having some troubles to understand how to form a simple query..

What I want to perform is a simple SELECT FROM in SQL but it seems I cannot get it done.

My table definition is basically:

Table name snsNotifications Primary partition key recipientId (Number) <--- This is a user id Primary sort key snsID (String) <--- This is the SNS message id

it follows some attributes (like readAt).

The query I want to perform is:

SELECT from snsNotifications WHERE recipientId=X and readAt=x

I even can perform this query on AWS UI: Screenshot

My lambda function uses the following :

var params = {
            TableName : "snsNotifications",
            KeyConditionExpression   : "recipientId = :recipientId and readAt = :readAt",
            ExpressionAttributeValues: {
                ":recipientId": parseInt(msg.recipientId),
                ":readAt"     : 0,
            }
        };

        docClient.query(params, function(err, data) {
            if (err) {
                console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
            } else {
                console.log("Query succeeded.");
                data.Items.forEach(function(item) { ... }

But i get the following error:

Unable to query. Error: { "message": "Query condition missed key schema element: snsID", "code": "ValidationException", "time": "2017-11-20T18:19:40.419Z", "requestId": "J73RIAE09GDRD1Q47I9OLCU7N7VV4KQNSO5AEMVJF66Q9ASUAAJG", "statusCode": 400, "retryable": false, "retryDelay": 44.175697630271316 }

So basically it is complaining of snsID (primary sort key) being not defined on the query itself.

Any lights? I bet is just some small detail.

Thanks in advance

2

2 Answers

6
votes

Replace the readAt in KeyConditionExpression with snsId. If you dont want to include the sort key and wanted to filter the data by non-key attribute readAt, use FilterExpression for it.

KeyConditionExpression can have only partition key or sort key. For non key attributes, you should use FilterExpression.

7
votes

Thank you @notionquest, that made the trick.

Attached answer to who may help:

var params = {
            TableName : "snsNotifications",
            KeyConditionExpression   : "recipientId = :recipientId",
            FilterExpression: "readAt = :readAt",
            ExpressionAttributeValues: {
                ":recipientId": parseInt(msg.recipientId),
                ":readAt"     : 0,
            }
        };