2014-02-12 14 views
5

Ist es möglich, einen exklusiven Startschlüssel anzugeben, wenn eine DynamoDB-Tabelle über globalen sekundären Index abgefragt wird?DynamoDB Globaler sekundärer Index mit exklusivem Startschlüssel

Ich benutze die aws-java-sdk Version 1.6.10 und Ausführen von Abfragen mit einem QueryExpression und einem DynamoDBMapper. Hier ist der Kern dessen, was ich versuche zu tun:

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); 

Daraus ergibt sich eine 400 Fehlermeldung, dass der angegebene Starttaste ungültig ist. Der TIMESTAMP ist der Bereichsschlüssel für den Tabellenindex und den globalen Sekundärindex, und das Attributwertpaar ist gültig (dh es gibt ein Element in der Tabelle, dessen Werte als Hash- und Bereichsschlüssel für den Index und als Attribut übergeben werden) übergeben, da der Index der Hash-Schlüssel des globalen Sekundärindex ist).

Gibt es etwas, was ich vermisst habe oder ist das nicht möglich?

Antwort

6

Per einem amazonischen, ist dies nicht möglich: https://forums.aws.amazon.com/thread.jspa?threadID=146102&tstart=0

Eine Abhilfe, die für meinen Anwendungsfall gearbeitet, war allerdings nur ein RangeKeyCondition größer als das letzte abgerufene Objekts Zeitstempel angeben. Hier ist die Idee:

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; 

Beachten Sie, dass die marshallIntoObject Verfahren zugunsten einer geschützten Methode in der DynamoDBMapper Klasse ist veraltet, aber es ist einfach genug, um einen Einweiser war ein zukünftiges Upgrade zu schreiben um die Zuordnung zu brechen.

Nicht so elegant wie mit dem Mapper, aber es erfüllt das gleiche.

+0

Ich war in der Lage, um dieses Problem, Zeitbereich explizit zu umgehen. Ich frage mich, wie wir das Problem lösen könnten, wenn der Sortierschlüssel des Sekundärindex nicht numerisch ist. Es sollte jetzt eine Lösung für dieses Problem von Amazon geben. – Sindhu

4

Hatte das gleiche Problem und wurde gerade sortiert. :) Zu spät, um die Frage zu beantworten, aber hoffe jemand wird hilfreich finden.

Wenn Sie oder Scan-Tabelle abfragen, mit Sekundärindizes und Paginierung, sollten Sie Primärschlüssel der Tabelle und den Index enthalten (als Schlüssel), mit zuletzt ermittelten Werten (als Attributwert), wenn Sie ExclusiveStartKey Einstellung.

Nur Sysout die LastEvaluatedKey aus der Abfrage oder Scan-Ergebnis, um das Format zu sehen.

// let's just assume that we have a table to store details of products 
Map<String, AttributeValue> exclusiveStartKey = new HashMap<String, AttributeValue>(); 
// primary key of the table 
exclusiveStartKey.put("productId", new AttributeValue().withS("xxxx")); 
exclusiveStartKey.put("produtSize", new AttributeValue().withS("XL")); 
// primary key of the index 
exclusiveStartKey.put("categoryId", new AttributeValue().withS("xx01")); 
exclusiveStartKey.put("subCategoryId", new AttributeValue().withN("1")); 
Verwandte Themen