amazon-dynamodb - DynamoDB放置项目ConditionalCheckFailedException

标签 amazon-dynamodb

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

A client error (ConditionalCheckFailedException) occurred when calling the PutItem operation: The conditional request failed



为什么ConditionExpression不允许我同时写两条记录? (我预计第二次操作后会有2条记录)

我怀疑这是因为使用了非关键条件,但是在docs中我没有看到任何表示缺乏对非关键条件的支持的信息。

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

create-table.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和事件2的哈希键和范围键具有相同的值。
    因此,第二个放置项将简单地覆盖第一个记录。
  • 您的ConditionExpression禁止将记录1替换为记录2

  • 在放置记录之前对ConditionExpression进行求值。您的表达式失败是因为,当您要插入事件2时,DynamoDB会发现已经存在具有aggregateId“id1”的记录。该条件在“attribute_not_exists(aggregateId)”上失败,并且您收到ConditionalCheckFailedException。此表达式防止记录2覆盖记录1。

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

    关于amazon-dynamodb - DynamoDB放置项目ConditionalCheckFailedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38733363/

    相关文章:

    amazon-web-services - 如何使用 Cloudformation 模板自动缩放 dynamodb 二级索引?

    java - java.lang.String 类型中没有@DynamoDBHashKey 注释的方法或字段

    node.js - AWS DynamoDB 查询不过滤 BOOL 值

    ios - 如何在没有 for 循环的情况下从 DynamoDB 中删除所有数据?

    Python Boto Dynamodb 对范围键的小记录集检索性能非常慢

    amazon-web-services - 如何将现有的 dynamodb 表架构导出为 json?

    amazon-web-services - DynamoDB 对重复全局二级索引的排序顺序

    amazon-web-services - 无法解码 dynamodb 属性

    node.js - 如何正确使用 list_append 来保持 DynamoDB 中的值唯一?

    node.js - 在 Alexa 响应中使用 Dynasty DynamoDB 查询