消除Dynamo Update查询的范围关键标准?

时间:2014-07-09 00:20:30

标签: android amazon-web-services amazon-dynamodb

如何让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”。在实践中,这会有所不同。

提前感谢您的帮助!

杰夫

1 个答案:

答案 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”能够唯一地标识一行时,它才真正让你受益:)