Skip to content

How can I query a Global Secondary Index with an additional filter using DynamoDBContext while taking advantage of the DynamoDBGlobalSecondaryIndexHashKey attribute

1

If I have this class:

[DynamoDBTable("users")]
public sealed class User
{
    [DynamoDBHashKey]
    [DyanmoDBProperty("login_name")]
    public string Identifier { get; set; }

    [DynamoDBGlobalSecondaryIndexHashKey("customer-users")]
    [DynamoDBProperty("customer_name")]
    public string Customer { get; set; }

    [DynamoDBProperty("is_active")]
    public bool IsActive { get; set; }

    [DynamoDBProperty("name")]
    public string Name { get; set; }
}

How can I use IDynamoDBContext to query the customer-users GSI while taking advantage of the attributes I've declared.

For example, I've tried this, but it doesn't seem to work:

ddbContext
        .QueryAsync<User>(customerName, new DynamoDBOperationConfig
        {
            IndexName = "customer-users",
            QueryFilter = [
                new ScanCondition(nameof(User.IsActive), ScanOperator.Equal, true)
            ]
        })
        .GetRemainingAsync();

What I don't want to do is make the use of [DynamoDBGlobalSecondaryIndexHashKey("customer-users")], [DynamoDBProperty("customer_name")], and [DynamoDBProperty("is_active")] redundant by specifying a key and filter expression as such: customer_name = :customername and is_active = :isactive, respectively.

asked a year ago470 views
2 Answers
1

QueryFilter should be a List<ScanCondition> like this:

await ddbContext.QueryAsync<User>(customerName, new DynamoDBOperationConfig
{
    IndexName = "customer-users",
    QueryFilter = new List<ScanCondition>
    {
        new ScanCondition(nameof(User.IsActive), ScanOperator.Equal, true)
    }
})
.GetRemainingAsync();
AWS
EXPERT
answered a year ago
  • Square bracket notation (collection expressions) is syntactic sugar for new List<T>() as of C# 12. Your code and my code are equivalent.

  • Oh thats nice, haven't used 12 yet. What exception message are you getting?

  • I get no exception at all. It's just not returning any data. If I remove QueryFilter or switch to using FromQueryAsync and use the more verbose mode of adding the filter--i.e. using FilterExpression and building the string--I get results. It's just while using QueryAsync and QueryFilter that I get no results instead of the ones I expect.

-2

To query a Global Secondary Index (GSI) with an additional filter using DynamoDBContext while taking advantage of the DynamoDBGlobalSecondaryIndexHashKey attribute, you can modify your approach slightly. The DynamoDBContext in the AWS SDK for .NET provides a way to query GSIs while respecting the attributes you've declared on your model.

Here's how you can query the "customer-users" GSI for active users of a specific customer:

var queryConfig = new DynamoDBOperationConfig
{
IndexName = "customer-users",
QueryFilter = new List<ScanCondition>
{
new ScanCondition("IsActive", ScanOperator.Equal, true)
}
};

var query = ddbContext.FromQueryAsync<User>(customerName, queryConfig);
var activeUsers = await query.GetRemainingAsync();

In this approach:

  1. We're using the FromQueryAsync<User> method instead of QueryAsync<User>. This method respects the DynamoDBGlobalSecondaryIndexHashKey attribute on the Customer property.

  2. We pass the customerName as the first parameter, which will be used as the hash key for the GSI query.

  3. We're still using the DynamoDBOperationConfig to specify the index name and the query filter.

  4. The QueryFilter is applied using the property name "IsActive" as defined in your User class, not the DynamoDB attribute name. The DynamoDBContext will automatically translate this to the correct attribute name ("is_active") based on your DynamoDBProperty attribute.

This approach takes full advantage of the attributes you've declared on your User class. The DynamoDBGlobalSecondaryIndexHashKey attribute is respected for the query key, and the DynamoDBProperty attributes are used for translating between your C# property names and the actual DynamoDB attribute names.

Remember that when querying a GSI, you can only retrieve attributes that are projected into the index. Make sure that the IsActive attribute is projected if you want to filter on it.
Sources
Working with Global Secondary Indexes: .NET - Amazon DynamoDB
Working with Global Secondary Indexes: Java - Amazon DynamoDB

answered a year ago
  • FromQueryAsync doesn't accept the GSI's hash key value as the first parameter. This code isn't valid.

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.