6

I have a DynamoDb table with a GSI over two keys - string field 'id' (partition key) and number field 'count' (sort key).

I'm trying to work out how to run a query (not scan) via a Spring Java application using the DynamoDbEnhancedClient in the SDK on this table for the key condition expression:

#id = :idValue and #count between :minCount and :maxCount

I can build two separate QueryConditional objects for each part of this compound expression, for example:

var partitionKeyConditional = QueryConditional.keyEqualTo(Key.builder()
      .partitionValue("myIdValue")
      .build());
var sortKeyConditional = QueryConditional.sortBetween(Key.builder()
      .sortValue(0)
      .build(), Key.builder()
      .sortValue(100)
      .build());

But I don't know how to combine these in the actual query request:

dynamoDbEnhancedClient.table(myTableName, TableSchema.fromBean(TableObject.class)) 
   .query(QueryEnhancedRequest.builder()
        .queryConditional(SomeJoinFunction??(partitionKeyConditional, sortKeyConditional))
        .build())
   .items();

I can see I could use a filterExpression, but I assume this would occur after the key conditions have been applied in the query to select results, so the advantage of the sort key definition is essentially lost. It most closely resembles the functionality that I want however:

    var expressionAttributeNames = new HashMap<String, String>() {{
        put("#id", ID_PROPERTY_NAME);
        put("#count", COUNT_PROPERTY_NAME);
    }};
    var expressionAttributeValues = new HashMap<String, AttributeValue>() {{
        put(":idValue", AttributeValue.builder().s("myId").build());
        put(":minCount", AttributeValue.builder().n("0").build());
        put(":maxCount", AttributeValue.builder().n("100").build());
    }};

    var queryExpression = Expression.builder()
            .expressionNames(expressionAttributeNames)
            .expressionValues(expressionAttributeValues)
            .expression("#id = :idValue and #count between :minCount and :maxCount")
            .build();

I am probably missing something obvious, any suggestions?

1 Answers1

8

The Key Builder used by the QueryConditionals can take both a partitionKey and sortKey value to build its expression. So when you build your QueryConditional.sortBetween object, you can define the matching partitionKey there:

var partitionKeyValue = "myIdValue"
var sortKeyConditional = QueryConditional.sortBetween(Key.builder()
  .partitionValue(partitionKeyValue)
  .sortValue(0)
  .build(), Key.builder()
  .partitionValue(partitionKeyValue)
  .sortValue(100)
  .build());
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Renato Costa
  • 81
  • 1
  • 4