2016-05-18 168 views
1

我的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; 
    } 
} 

回答

0

該服務的錯誤消息說,你需要把: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; 
+0

謝謝。我會盡力而且可以重做解決方案。 – Kent