2
votes

I am trying to filter the data returned by a dynamodb scan operation using nodejs aws sdk but the data returned has 0 items.

Response : {"Items":[],"Count":0,"ScannedCount":15}

I have tried with both FilterExpression and ScanFilter but getting the same result.

FilterExpression:

var params = {
            TableName: tableName,
            FilterExpression: 'active = :active',
            ExpressionAttributeValues: {
                ':active': {
                    S: '1'
                }
            }
        };

ScanFilter:

var params = {
            TableName: tableName,
            ScanFilter: {
                'active': {
                    "AttributeValueList": [{ "S": "1" }],
                    "ComparisonOperator": "EQ"
                }
            }
        };

Here is the nodejs code:

        dynamodb.scan(params, onScan);

        function onScan(err, data) {
            if (err) {
                console.error('Unable to scan the table. Error JSON:', JSON.stringify(err, null, 2));
            } else {
                if (typeof data.LastEvaluatedKey != 'undefined') {
                    params.ExclusiveStartKey = data.LastEvaluatedKey;
                    dynamodb.scan(params, onScan);
                }
                if (data && data.Items)
                    callback(data.Items);
                else
                    callback(null);
            }
        }

I checked the same filter condition in the dynamodb console and getting the expected result.

dynamodb console screenshot

3
Is your code getting into the LastEvaluatedKey != 'undefined' condition? In other words are you dealing with more than one call to dynamodb.scan()? What is the code for the callback() function? This isn't running in a Lambda function is it?Mark B
@MarkB No, the code is not dealing with more than one call to dynamodb.scan() and the callback is a node express application running on an EC2 instance.acnn
can you try ExpressionAttributeValues : {':active': '1'} in the FilterExpressionsbharathp

3 Answers

6
votes

@bharathp answer did the trick for me,

in aws command line had to specify the parameter as {"S":"s1"}

aws dynamodb scan \
 --table-name aws-nodejs-typescript-dev \
 --filter-expression "id = :search" \
 --expression-attribute-values '{":search":{"S":"s1"}}'

in node code just ":search": "s1"

const params = {
  TableName: process.env.DYNAMODB_TABLE,
  ExpressionAttributeValues: {
    ":search": "s1"
  },
  FilterExpression: "id = :search",
  ProjectionExpression: "id",
};

dynamoDb.scan(params, (error, result) => {
3
votes

This was working just fine for me on AWS CLI,

aws dynamodb scan \

 --table-name myTableName \
 --filter-expression "email = :a" \
 --expression-attribute-values '{":a":{"S":"[email protected]"}}'

However when trying to write the same query on NodeJs/Angular5/typescript it fails:

private getDynamoEmail(email: string): Promise<ScanOutput> {
    const params: any = {
     TableName: this.config.database.myTableHere,
     KeyConditionExpression "email = :e" 
     ExpressionAttributeValues: {
      ":email": {
        S: email, // Had to remove this part to work and use 
                  // ExpressionAttributeNames instead
       },
     },
     FilterExpression: ":e = :email",
    };
    return this.docClient.scan(params).promise();
}

In order to work I had to omit the attribute type so here is the code working:

private getDynamoEmail(email: string): Promise<ScanOutput> {
    // tslint:disable-next-line:no-any
    const params: any = {
     ExpressionAttributeNames: {"#email": "email"},
     ExpressionAttributeValues: {":email": email},
     FilterExpression: "#email = :email",
     TableName: this.config.database.registeredLiveAccounts,
    };
    return this.docClient.scan(params).promise();
}

Hope helps Daniel

1
votes

It indicates that 15 items are scanned and no items found. You might find the item in your loop of:

if (typeof data.LastEvaluatedKey != 'undefined') {
  params.ExclusiveStartKey = data.LastEvaluatedKey;
  dynamodb.scan(params, onScan);
}

As scan operation scans all the items and filters the match.