0

I've tried my first attempt on using DynamoDB after a long time using relational databases, this is now being done to update test results for later analysis, consider the following table and secondary index

1 2

I've been trying to get for a given testName, the test runs in a known range of revisions using the following Java code :

HashMap<String, Condition> scanMap = new HashMap<>();
scanMap.put("revision", new Condition().withComparisonOperator(ComparisonOperator.BETWEEN).withAttributeValueList(Arrays.asList(new AttributeValue("N:"+String.valueOf(minRev)), new AttributeValue("N:"+String.valueOf(maxRev)))));
scanMap.put("testName", new Condition().withComparisonOperator(ComparisonOperator.EQ).withAttributeValueList(new AttributeValue(Collections.singletonList(testName))));
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression().withScanFilter(scanMap);
scanExpression.setIndexName("testName-revision-index");
List<ValidationReport> reports = getMapper().scan(ValidationReport.class, scanExpression);

I've tried to remove the "N:" with no luck. Removing the revision expression altogether return all the test runs with no limitation on the revision range

Any help would be appreciated here

1 Answer 1

1

So, it seems like I was barking at the wrong tree here, trying to use Scan instead of Query :

The customer should not use ScanFilter, which is deprecated. List/Map datatypes are better suited to the new FilterExpression syntax. I suspect the problem is with the multi-value attribute with "N:" in the name; this doesn't seem close to the wire format. To use the "new" filter expressions, they should create ExpressionAttributeNames and ExpressionAttributeValues to tell the AWS SDK about the attributes for the filter, addExpressionAttributeNamesEntry and addExpressionAttributeValuesEntry.http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBScanExpression.html Also, I would be remiss if I didn't point out that Scan is absolutely not the right API action for this query; Query is the correct action. testName should be used with Query with a KeyConditionExpression to narrow the search down to the correct partition, and revision should be added to the same with the BETWEEN syntax. Scan is intended for backups and background operations, and in this case the customer's index schema can be used with Query to narrow the search. Caution them about using Scan; this is a fundamental best practice:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScanGuidelines.html

So I've used Query instead :

    Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();
    eav.put(":v1", new AttributeValue().withS(testName));
    eav.put(":v2", new AttributeValue().withS(version));
    eav.put(":v3", new AttributeValue().withN(String.valueOf(minRev)));
    eav.put(":v4", new AttributeValue().withN(String.valueOf(maxRev)));

    final DynamoDBQueryExpression<ValidationReport> query = new DynamoDBQueryExpression<>();
    query.withKeyConditionExpression("testName = :v1");
    query.withFilterExpression("buildVersion = :v2 and revision BETWEEN :v3 AND :v4");
    query.setConsistentRead(false);
    query.withExpressionAttributeValues(eav);
    return getMapper().query(ValidationReport.class, query);`

Please note that when using the AttributeValue there's quite a difference between the following :

new AttributeValue().withS("SomeStringValue")
new AttributeValue().withN("SomeNumber")

Which is what I was missing

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.