通过全局二级索引查询DynamoDB表时是否可以指定独占启动键?
我正在使用aws-java-sdk版本1.6.10并使用QueryExpression和DynamoDBMapper执行查询.这是我要做的事情的要点:
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);
这会导致400错误,指出指定的开始键无效. TIMESTAMP是表索引和全局二级索引的范围键,属性值对是有效的(即表中有一个项目,其值作为索引的哈希和范围键传递,属性传递为索引是全局二级索引的哈希键).
有什么我错过了或这是不可能的?
解决方法
根据亚马逊流域,这是不可能的:
https://forums.aws.amazon.com/thread.jspa?threadID=146102&tstart=0
但是,对我的用例有用的解决方法是仅指定一个大于上次检索到的对象的时间戳的RangeKeyCondition.这是个主意:
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;
请注意,不推荐使用marshallIntoObject方法,而是支持DynamoDBMapper类中的受保护方法,但是编写marshaller很容易进行未来的升级以打破映射.
不像使用映射器那样优雅,但它完成了同样的事情.