【问题标题】:DynamoDb putItem ConditionExpression in c++ - add or updatec++ 中的 DynamoDb putItem ConditionExpression - 添加或更新
【发布时间】:2017-02-12 20:28:52
【问题描述】:

我的 putItem 正在工作。现在我想确保只更新现有项目的新信息,或者将其添加为新项目:

条件表达式:

  • 如果 partition:sort 不存在则创建新项目
  • 如果属性生成则更新

所以我在代码中添加了一行:

    putItemRequest.SetConditionExpression(" attribute_not_exists(" + partitionName + ") OR (attribute_exists(" + partitionName + ") AND (" + timestampName + " < :" + timestamp + "))");

这应该会创建一个新项目,但它似乎正在尝试评估新项目不存在的属性“生成”。

putItem 返回的错误:

Invalid ConditionExpression:未定义表达式中使用的表达式属性值;属性值::1461782160

在调试器中,conditionExpression 如下所示:

m_conditionExpression = "attribute_not_exists(airport) OR (attribute_exists(airport) AND (generated

我试图避免:

  • 查找分区:排序
  • 如果不存在,放Item
  • 否则检查生成的属性
  • 那么如果生成

有没有办法构造条件表达式来满足我的期望?

编辑:使用 updateItem 时出现同样的问题

代码:

UpdateItemRequest updateItemRequest;
updateItemRequest.WithTableName(dynamoDbTableName);

AttributeValue hashPartition;
hashPartition.SetS(partition);
updateItemRequest.AddKey(partitionName, hashPartition);

AttributeValue hashSort;
hashSort.SetS(sort);
updateItemRequest.AddKey(sortName, hashSort);

AttributeValue hashAttribute;
hashAttribute.SetS(attribute);
Aws::Map<Aws::String, AttributeValue> attributeMap;
attributeMap[":a"] = hashAttribute;

updateItemRequest.SetUpdateExpression("SET " + timestampName + " = :" + timestamp + ", " + attributeName + " = :a");

updateItemRequest.SetExpressionAttributeValues(attributeMap);

// Allow only older items to be updated
updateItemRequest.SetConditionExpression("(" + timestampName + " < :" + timestamp + ")");

auto updateItemOutcome = dynamoDbClient.UpdateItem(updateItemRequest);

错误:

Invalid UpdateExpression:未定义表达式中使用的表达式属性值;属性值::1461781980

那个属性值就是时间戳。它没有被定义,因为这个项目不存在并且应该被创建。

这是我目前的工作

ClientConfiguration config;
config.region = Aws::Region::US_WEST_2;
Aws::DynamoDB::DynamoDBClient dynamoDbClient(config);

Aws::Map<Aws::String, AttributeValue> aMap;

PutItemRequest putItemRequest;
putItemRequest.WithTableName(dynamoDbTableName);

AttributeValue hashPartition;
hashPartition.SetS(partition);
putItemRequest.AddItem(partitionName, hashPartition);
aMap[":p"] = hashPartition;

AttributeValue hashSort;
hashSort.SetS(sort);
putItemRequest.AddItem(sortName, hashSort);
aMap[":s"] = hashSort;

AttributeValue hashTimestamp;
hashTimestamp.SetN(timestamp);
putItemRequest.AddItem(timestampName, hashTimestamp);

AttributeValue hashAttribute;
hashAttribute.SetS(attribute);
putItemRequest.AddItem(attributeName, hashAttribute);

// Do not update existing items
putItemRequest.SetConditionExpression("NOT((" + partitionName + " = :p) AND (" + sortName + " = :s))");
putItemRequest.SetExpressionAttributeValues(aMap);

auto putItemOutcome = dynamoDbClient.PutItem(putItemRequest);

if(putItemOutcome.IsSuccess())
{
    poco_information(logger, "writeDb PutItem Success: " + partition + ":" + sort);
    status = SWIMPROCESSOR_OK;
}
else
{
    if(putItemOutcome.GetError().GetErrorType() == DynamoDBErrors::CONDITIONAL_CHECK_FAILED) {
        // item exists, try to update
        Aws::Map<Aws::String, AttributeValue> uMap;
        uMap[":t"] = hashTimestamp;
        uMap[":a"] = hashAttribute;

        UpdateItemRequest updateItemRequest;
        updateItemRequest.WithTableName(dynamoDbTableName);
        updateItemRequest.AddKey(partitionName, hashPartition);
        updateItemRequest.AddKey(sortName, hashSort);
        updateItemRequest.SetUpdateExpression("SET " + timestampName + " = :t, " + attributeName + " = :a");
        updateItemRequest.SetExpressionAttributeValues(uMap);

        // Allow only older items to be updated
        updateItemRequest.SetConditionExpression(timestampName + " < :t");

        auto updateItemOutcome = dynamoDbClient.UpdateItem(updateItemRequest);

        if(updateItemOutcome.IsSuccess())
        {
            poco_information(logger, "writeDb UpdateItem Success: " + partition + ":" + sort);
            status = SWIMPROCESSOR_OK;
        }
        else
        {
            if(putItemOutcome.GetError().GetErrorType() == DynamoDBErrors::CONDITIONAL_CHECK_FAILED) {
                poco_information(logger, "writeDB UpdateItem new timestamp is older then current timestamp");
                status = SWIMPROCESSOR_OK;
            } else {
                std::string msg(updateItemOutcome.GetError().GetMessage());
                poco_error(logger, "writeDb UpdateItem Failure: " + msg);
                status = SWIMPROCESSOR_DBWRITEERROR;
            }
        }

    } else {
        std::string msg(putItemOutcome.GetError().GetMessage());
        poco_error(logger, "writeDb PutItem Failure: " + msg);
        status = SWIMPROCESSOR_DBWRITEERROR;
    }
}

【问题讨论】:

    标签: c++ amazon-web-services amazon-dynamodb


    【解决方案1】:

    该服务的错误消息说您需要将:1461782160 放入attributeMap。 UpdateExpression 应该是"SET " + timestampName + " = :timestamp, " + attributeName + " = :a" 并且您的地图应定义如下。

    AttributeValue hashAttributeA;
    hashAttributeA.SetS(attribute)
    AttributeValue hashAttributeTimestamp;
    hashAttributeTimestamp.SetN(timestamp)
    Aws::Map<Aws::String, AttributeValue> attributeMap;
    attributeMap[":a"] = hashAttributeA;
    attributeMap[":timestamp"] = hashAttributeTimestamp;
    

    【讨论】:

    • 谢谢。我会尝试,我将能够重新设计解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多