Filter Expression not working in DynamoDb Table

0

I have a DynamoDb Table named "MenuItem" which has GSI named "CategoryId-CreatedDate-index" CategoryId is the Partition Key and CreatedDate is the Sort key. I am doing the following query operation in the AWS Console and getting 28 records as shown in the below screenshot.

Filter Error

But when I am doing the same thing via C# code then I am getting zero row count.

var menuRequest = new QueryRequest
            {
                TableName = MenutableName,
                IndexName = "CategoryId-CreatedDate-index",
                Limit = 10,
                ScanIndexForward = false,
                 KeyConditionExpression = "CategoryId = :v_Id",
                FilterExpression = "IsPublished = :ispub",
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>
                {
                    {":v_Id", new AttributeValue { N =  "1" }},
                    {":ispub", new AttributeValue { BOOL = true }},
                }
            };

var menuResponse = await client.QueryAsync(menuRequest).ConfigureAwait(false);

Filter_Expression_c#_code_error

Atif
asked 8 months ago654 views
2 Answers
2
Accepted Answer

Issue Explained

You API is not returning item due to the use of Limit = 10 parameter.

A single Query operation will read up to the maximum number of items set (if using the Limit parameter) or a maximum of 1 MB of data and then apply any filtering to the results using FilterExpression.

reference

So in your case, you read 10 items, apply the filter IsPublished=true, of which there are no matches, so you get returned an empty response.

ScannedCount

The number of items evaluated, before any QueryFilter is applied. A high ScannedCount value with few, or no, Count results indicates an inefficient Query operation

Count

The number of items in the response. If you used a QueryFilter in the request, then Count is the number of items returned after the filter was applied, and ScannedCount is the number of matching items before the filter was applied. If you did not use a filter in the request, then Count and ScannedCount are the same.

Resolution

To overcome this issue you can:

  1. Increase the limit, also consider using pagination incase your item collection exceed 1MB.
  2. Re-design your data model to include the IsPublished attribute as part of your sort key:
GSIPKGSISKIsPublished
CategoryId123false#2023-09-11T20:00:000zfalse
CategoryId123false#2023-09-11T21:00:000zfalse
CategoryId123true#2023-09-11T17:00:000ztrue
CategoryId123true#2023-09-11T10:00:000ztrue

This approach you can use Limit=10 and get exactly 10 items:

var menuRequest = new QueryRequest
            {
                TableName = MenutableName,
                IndexName = "CategoryId-CreatedDate-index",
                Limit = 10,
                ScanIndexForward = false,
                 KeyConditionExpression = "CategoryId = :v_Id AND begins_with(GSISK, :tt)",
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>
                {
                    {":v_Id", new AttributeValue { N =  "1" }},
                    {":tt", new AttributeValue { S = "true" }},
                }
            };
profile pictureAWS
EXPERT
answered 8 months ago
profile pictureAWS
EXPERT
reviewed 8 months ago
0

Hi Atif,

The important thing to consider when using a Query Filter is the order that DynamoDB processes actions:

  1. Read items from your table
  2. If a filter expression is present, remove items that don't match the filter
  3. Return items

Your Query includes a Limit for the Query, so I suspect what's happening is that DynamoDB is reading 10 records as indicated by your "Limit=10", applying the filter to these 10 records, finds that none of them match your filter so returns (correctly) 0 items to you. In your output image you can see that "Scanned Count" is 10 showing that 10 records have been processed, but none have been returned.

I suggest having a read of the blog "When to use (and when not to use) DynamoDB Filter Expressions" as it explains what's going on and gives alternatives for how to query your data. With the information you've provided I suggest experimenting with using a new Global Secondary Index with CategoryId as the PK and IsPublished as the Sort Key. This should be a more efficient query for the use case you've described in your question, and will mean you can do a Query without using a Filter expression.

AWS
answered 8 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions