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
已提問 8 個月前檢視次數 672 次
2 個答案
3
已接受的答案

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
專家
已回答 8 個月前
profile picture
專家
已審閱 7 天前
profile pictureAWS
專家
已審閱 8 個月前
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
已回答 8 個月前

您尚未登入。 登入 去張貼答案。

一個好的回答可以清楚地回答問題並提供建設性的意見回饋,同時有助於提問者的專業成長。

回答問題指南