如何让Dynamo的UpdateItemRequest忽略范围键,或者进行粗略测试,例如not null?
我正在使用范围键,其中包含记录更新的时间。另外,我使用不是键的ID字段更新我选择的行。我使用UpdateItemRequest中的expectedAttribute更新ID字段。 Dynamo的UpdateItemRequest强制我指定范围键值。我的ID更新代码不知道范围键值。我可以以某种方式不指定范围键而不会出错吗?或者我可以提供一个简单的范围键测试,如不是null?
当我删除范围键时,AWS会抛出一个错误,“提供的关键元素与架构不匹配”
// construct the update map
HashMap<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
AttributeValue av = new AttributeValue().withN("1");
AttributeValueUpdate avu = new AttributeValueUpdate().withValue(av).withAction(AttributeAction.PUT);
updates.put("Column1", avu);
AttributeValue av2 = new AttributeValue().withN("2");
AttributeValueUpdate avu2 = new AttributeValueUpdate().withValue(av2).withAction(
AttributeAction.PUT);
updates.put("Column2", avu2);
// construct the key map
HashMap<String, AttributeValue> keyMap = new HashMap<String, AttributeValue>();
AttributeValue hashValue = new AttributeValue().withN("10");
keyMap.put("hashKey", hashValue);
AttributeValue lastModKeyValue = new AttributeValue().withN("1404175127074");
// ****** I want to remove this key but Dynamo throws an error
keyMap.put("problemRangeKey", lastModKeyValue);
// expected value comparison
AttributeValue idValue = new AttributeValue().withN("100");
ExpectedAttributeValue expected = new ExpectedAttributeValue(idValue);
UpdateItemRequest request = new UpdateItemRequest().withTableName(DatabaseConstants.CHART_TABLE)
.withKey(keyMap).withAttributeUpdates(updates).addExpectedEntry(ID, expected);
ddb.updateItem(request);
为清楚起见,以下是我如何使用范围键在特定时间后查找行。如果我删除此时间范围,那么每次在特定时间后查找行时,我都会进行大扫描。
Map keyConditions = new HashMap();
AttributeValue attribute = new AttributeValue().withN("10");
Condition hashKeyCondition = new Condition().withComparisonOperator(ComparisonOperator.EQ.toString())
.withAttributeValueList(attribute);
keyConditions.put("hashKey", hashKeyCondition);
// specify new records
long lastQueryTime = PrefsActivity.getLastDynamoQueryTime(activity);
String lastTimeString = String.valueOf(lastQueryTime);
Log.v(TAG, "get Charts from dynamo that are after " + lastTimeString);
// update the query time to now
long now = System.currentTimeMillis();
PrefsActivity.setLastDynamoQueryTime(activity, now);
AttributeValue timeAttribute = new AttributeValue().withN(lastTimeString);
Condition timeCondition = new Condition().withComparisonOperator(ComparisonOperator.GT.toString())
.withAttributeValueList(timeAttribute);
keyConditions.put("problemRangeKey", timeCondition);
List<Map<String, AttributeValue>> ChartsInMaps = new ArrayList<Map<String, AttributeValue>>();
Map lastEvaluatedKey = null;
QueryRequest request = new QueryRequest().withTableName("tableName")
.withKeyConditions(keyConditions).withExclusiveStartKey(lastEvaluatedKey);
QueryResult result = ddb.query(request);
我正在使用最新的AWS Android SDK。在上面的示例中,我将hashKey设置为“10”。在实践中,这会有所不同。
提前感谢您的帮助!
杰夫
答案 0 :(得分:0)
问题是,您希望更新具有特定hashKey值和特定列值的所有项目(列名称为id)。
该表是Hash-Range架构。由于您不知道范围键,因此必须使用该hashKey获取所有行,然后根据列值(ID == value)执行过滤。您可以使用query filter来有效地执行此操作。然后,对于查询中的每一行,执行具有预期值(ID == value)的条件put,以确保。
QueryRequest request = new QueryRequest();
// set up query request (table name, etc)
// set up query filter (ID == value)
QueryResponse response = client.query(request)
for (item in response.items):
PutItemRequest req = new PutItemRequest();
// set up put item request
// set up primary key for item to update
// hashkey = item.hashkey
// rangekey = item.rangeKey
// set up expected value (ID == value)
client.updateItem(req)
另一方面,由于您希望在特定时间之后有效地查询所有行,因此您可以创建一个Local Secondary Index,其中“time”作为范围键,而不是将“time”作为您的范围键基表。您仍然可以使用LSI进行高效查询(与扫描表和按时间过滤相比)。更重要的是,如果您的“ID”属性可以使用您的哈希键唯一标识一行,则可以将“ID”作为基表的范围键。这样您就可以有效地更新项目,因为您已经知道了hashkey值和范围键值(id值)。
当你的hashkey和“ID”能够唯一地标识一行时,它才真正让你受益:)