我的putItem正在工作。現在,我要確保我只更新新的信息,以現有項目,或將它作爲一個新項目:DynamoDb putItem ConditionExpression in C++ - 添加或更新
ConditionlExpression:
- 創建新的項目,如果分區:排序不存在
- 如果更新屬性生成<:newTimestamp
所以我添加一行代碼:
putItemRequest.SetConditionExpression(" attribute_not_exists(" + partitionName + ") OR (attribute_exists(" + partitionName + ") AND (" + timestampName + " < :" + timestamp + "))");
這應該會創建一個新項目,但它似乎試圖在新項目不存在時評估「生成」屬性。
上putItem返回錯誤:
Invalid ConditionExpression: An expression attribute value used in expression is not defined; attribute value: :1461782160
從調試器conditionExpression樣子:
m_conditionExpression = " attribute_not_exists(airport) OR (attribute_exists(airport) AND (generated < :1461782160))"
我試圖避免:
- 查找分區:排序
- 如果它不存在,putItem
- 別的檢查生成的屬性
- 那麼如果產生< newTimestamp更新項目
有沒有一種方法來構建conditionExpression,以滿足我的期望呢?
編輯:同樣的問題使用的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: An expression attribute value used in expression is not defined; attribute value: :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;
}
}
謝謝。我會盡力而且可以重做解決方案。 – Kent