Java – dynamodb global secondary index with exclusive startup key

Can I specify an exclusive startup key when querying dynamodb table through global secondary index?

I am using AWS Java SDK version 1.6 10 and use queryexpression and dynamodmapper to execute the query This is the point of what I want to do:

MappedItem key = new MappedItem();
item.setIndexedAttribute(attributeValue);

Map<String,AttributeValue> exclusiveStartKey = new HashMap<String,AttributeValue>();
exclusiveStartKey.put(MappedItem.INDEXED_ATTRIBUTE_NAME,new AttributeValue().withS(attributeValue));
exclusiveStartKey.put(MappedItem.TIMESTAMP,new AttributeValue().withN(startTimestamp.toString()));

DynamoDBQueryExpression<MappedItem> queryExpression = new DynamoDBQueryExpression<MappedItem>();
queryExpression.withIndexName(MappedItem.INDEX_NAME);
queryExpression.withConsistentRead(Boolean.FALSE);
queryExpression.withHashKeyValues(key);
queryExpression.setLimit(maxResults * 2);
queryExpression.setExclusiveStartKey(exclusiveStartKey);

This causes a 400 error indicating that the specified start key is invalid Timestamp is the range key of the table index and the global secondary index, and the attribute value pair is valid (that is, there is an item in the table whose value is passed as the hash and range key of the index, and the attribute passed as the index is the hash key of the global secondary index)

What did I miss or is it impossible?

Solution

According to the Amazon basin, this is impossible: https://forums.aws.amazon.com/thread.jspa?threadID=146102&tstart=0

However, a useful workaround for my use case is to specify only a rangekeycondition that is greater than the timestamp of the last retrieved object This is an idea:

Condition hashKeyCondition = new Condition();
hashKeyCondition.withComparisonOperator(ComparisonOperator.EQ).withAttributeValueList(new AttributeValue().withS(hashKeyAttributeValue));

Condition rangeKeyCondition = new Condition();
rangeKeyCondition.withComparisonOperator(ComparisonOperator.GT).withAttributeValueList(new AttributeValue().withN(timestamp.toString()));

Map<String,Condition> keyConditions = new HashMap<String,Condition>();
keyConditions.put(MappedItem.INDEXED_ATTRIBUTE_NAME,hashKeyCondition);
keyConditions.put(MappedItem.TIMESTAMP,rangeKeyCondition);


QueryRequest queryRequest = new QueryRequest();
queryRequest.withTableName(tableName);
queryRequest.withIndexName(MappedItem.INDEX_NAME);
queryRequest.withKeyConditions(keyConditions);

QueryResult result = amazonDynamoDBClient.query(queryRequest);

List<MappedItem> mappedItems = new ArrayList<MappedItem>();

for(Map<String,AttributeValue> item : result.getItems()) {
    MappedItem mappedItem = dynamoDBMapper.marshallIntoObject(MappedItem.class,item);
    mappedItems.add(mappedItem);
}

return mappedItems;

Please note that the marshallintoobject method is not recommended. Instead, it supports the protected methods in the dynamodbmapper class. However, it is easy to upgrade the marshaler in the future to break the mapping

It's not as elegant as using a mapper, but it does the same thing

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>