DynamoDB放入项目ConditionalCheckFailedException



给定下面定义的表模式(create-table.json),在使用add-event1.jsonadd-event2.json:调用put-item后,我得到以下错误

调用PutItem操作时发生客户端错误(ConditionalCheckFailedException):条件请求失败

为什么ConditionExpression不允许我同时写入这两条记录?(我希望在第二次操作后有2条记录)

我怀疑这是因为使用了非关键条件,但我在文档中没有看到任何迹象表明缺乏对非关键条件的支持。

创建表格

$ aws dynamodb create-table --cli-input-json file://create-table.json

创建表.json

{
    "TableName": "EVENTS_TEST",
    "KeySchema": [
      { "AttributeName": "aggregateId", "KeyType": "HASH" },
      { "AttributeName": "streamRevision", "KeyType": "RANGE" }
    ],
    "AttributeDefinitions": [
      { "AttributeName": "aggregateId", "AttributeType": "S" },
      { "AttributeName": "streamRevision", "AttributeType": "N" }
    ],
    "ProvisionedThroughput": {
      "ReadCapacityUnits": 10,
      "WriteCapacityUnits": 10
    }
 }

添加第一条记录

$ aws dynamodb put-item --cli-input-json file://add-event1.json

add-event1.json

{
  "TableName": "EVENTS_TEST",
  "Item": {
    "aggregateId": { "S": "id" },
    "id": { "S": "119" },
    "context": { "S": "*" },
    "aggregate": { "S": "*" },
    "streamRevision": { "N": "0" },
    "commitId": { "S": "1119" },
    "commitSequence": { "N": "0" },
    "commitStamp": { "N": "1470185631511" },
    "dispatched": { "BOOL": false },
    "payload": { "S": "{ "event": "bla" }" }
  },
  "ExpressionAttributeNames": { "#name": "aggregate" },
  "ConditionExpression": "attribute_not_exists(aggregateId) and attribute_not_exists(streamRevision) and #name <> :name and context <> :ctx",
  "ExpressionAttributeValues": {
    ":name": { "S": "*" },
    ":ctx": { "S": "*" }
  }
}

添加第二条记录

$ aws dynamodb put-item --cli-input-json file://add-event2.json

add-event2.json

{
  "TableName": "EVENTS_TEST",
  "Item": {
    "aggregateId": { "S": "id" },
    "id": { "S": "123" },
    "context": { "S": "myCtx" },
    "aggregate": { "S": "myAgg" },
    "streamRevision": { "N": "0" },
    "commitId": { "S": "1123" },
    "commitSequence": { "N": "0" },
    "commitStamp": { "N": "1470185631551" },
    "dispatched": { "BOOL": false },
    "payload": { "S": "{ "event": "bla2" }" }
  },
  "ExpressionAttributeNames": { "#name": "aggregate" },
  "ConditionExpression": "aggregateId <> :id and streamRevision <> :rev and #name <> :name and context <> :ctx",
  "ExpressionAttributeValues": {
     ":id": { "S": "id" },
     ":rev": { "N": "0" },
     ":name": { "S": "myAgg" },
     ":ctx": { "S": "myCtx" }
  }
}

您的目标是保存这两条记录。这里有2个问题

  1. 使用您选择的哈希和范围键,不可能同时保存这两个记录

散列和范围键的组合使记录具有唯一性。事件1和事件2具有相同的哈希值和范围键值。因此,第二个输入项将简单地覆盖第一个记录。

  1. 您的ConditionExpression阻止用记录2替换记录1

ConditionExpression在放入记录之前进行求值。您的表达式失败,因为在即将插入事件2时,DynamoDB发现aggregateId为"id1"的记录已经存在。条件在"attribute_not_exists(aggregateId)"上失败,并且您收到ConditionalCheckFailedException此表达式可防止记录2覆盖记录1。

如果您想保存这两条记录,您必须选择另一种哈希键和/或范围键,以更好地表示数据项的唯一性。使用ConditionExpression无法解决此问题。

我收到了类似的错误。

The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: SMNKMSKJNSHBSGHVGHSB)

在我的情况下,我没有在表中添加排序键,我的第二个项目与第一个项目具有相同的主键。添加排序键后,它就起作用了。

解决方案

表中存在一个ID为allready的项。

您需要为尝试添加的项目创建一个唯一的ID。

相关内容

  • 没有找到相关文章

最新更新