Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.net Querying a Global Secondary Index in DynamoDB via DynamoDBContext

I have a dynamoDB table with a schema as follows:

var request = new CreateTableRequest
{
    TableName = tableName,
    KeySchema = new List<KeySchemaElement>
    {
        new KeySchemaElement("CompanyId", KeyType.HASH),
        new KeySchemaElement("Timestamp", KeyType.RANGE)
    },
    AttributeDefinitions = new List<AttributeDefinition>
    {
        new AttributeDefinition("CompanyId", ScalarAttributeType.S),
        new AttributeDefinition("Timestamp", ScalarAttributeType.N),
        new AttributeDefinition("UserId", ScalarAttributeType.S)
    },
    GlobalSecondaryIndexes = new List<GlobalSecondaryIndex>
    {
        new GlobalSecondaryIndex
        {
            IndexName = "UserIndex",
            KeySchema = new List<KeySchemaElement>
            {
                new KeySchemaElement("UserId", KeyType.HASH),
                new KeySchemaElement("Timestamp", KeyType.RANGE)
            },
            Projection = new Projection {ProjectionType = "ALL"},
            ProvisionedThroughput = new ProvisionedThroughput(5, 6)
        }
    },
    ProvisionedThroughput = new ProvisionedThroughput(5, 6)
};

I can query the primary key successfully as follows:

var client = new AmazonDynamoDBClient();
using (var context = new DynamoDBContext(client))
{
    var sortKeyValues = new List<object>{minTimestamp};
    result = await context.QueryAsync<AuditLogEntry>(companyId, QueryOperator.GreaterThanOrEqual, sortKeyValues,
                            new DynamoDBOperationConfig {OverrideTableName = TableName}).GetRemainingAsync();
}

And I can query the global secondary index without any constraint on the range key as follows:

var client = new AmazonDynamoDBClient();
using (var context = new DynamoDBContext(client))
{
    result = await context.QueryAsync<AuditLogEntry>(userId, new DynamoDBOperationConfig {OverrideTableName = TableName, IndexName = indexName})
        .GetRemainingAsync();
}

But when I try to query the index with a range key constraint:

var client = new AmazonDynamoDBClient();
using (var context = new DynamoDBContext(client))
{
    var sortKeyValues = new List<object> {minTimestamp};
    result = await context.QueryAsync<AuditLogEntry>(userId, QueryOperator.GreaterThan, sortKeyValues, new DynamoDBOperationConfig {OverrideTableName = TableName, IndexName = indexName}).GetRemainingAsync();
}

I get the following error:

Exception thrown: 'System.InvalidOperationException' in AWSSDK.DynamoDBv2.dll

Additional information: Local Secondary Index range key conditions are used but no index could be inferred from model. Specified index name = UserIndex

Googling this error hasn't thrown any light on the issue. The reference to Local Secondary Index has me confused because I'm using a Global index, but I just can't see what's wrong with my code.

I've been able to get the query working by querying directly on the AmazonDynamoDBClient rather than using DynamoDBContext, but I'd really like to understand what I'm doing wrong and be able to use DynamoDBContext.

Any ideas would be appreciated.

like image 826
avocados Avatar asked Sep 19 '16 03:09

avocados


1 Answers

In your model definition for AuditLogEntry you need to decorate properties that are part of the global secondary index with attributes - [DynamoDBGlobalSecondaryIndexRangeKey] and or [DynamoDBGlobalSecondaryIndexHashKey]

like image 94
camelCaseWarrior Avatar answered Oct 26 '22 19:10

camelCaseWarrior