首页 > 解决方案 > DynamoDB 事务

问题描述

我有一个用户表,键为 {id: hash, email: range} 并且我只想在不存在具有相同电子邮件的用户时创建一个用户。我正在尝试使用事务,所以我认为我需要使用一个条件:

case Dynamo.transact_write_items([
           {
             :condition_check,
             {
               table_name(),
               %{id: user_id, email: email},
               condition_expression: "email <> :email",
               expression_attribute_values: [email: email]
             }
           },
           {
             :put,
             {
               table_name(),
               new_user
             }
           }
         ])
         |> ExAws.request() do
      {:ok, _} -> {:ok, new_user}
      {:error, _} -> {:error, "unable to create user"}
    end

这不起作用,我有以下问题:

  1. 在 key 参数中,在条件中,我必须指定:%{id: user_id, email: email},但我必须指定user_id,它仍然不存在,我只生成了它。如何定义没有值的键?
  2. 我有以下错误:Transaction request cannot include multiple operations on one item,所以我想,鉴于我在条件中定义键的方式,它将检查和放置计算为同一实体上的两个操作。如何以一致的方式(以及在事务中)检查实体的存在?

这里的 Elixir 代码当然不相关,这只是我使用的语言:)

标签: amazon-dynamodbelixir

解决方案


根据文档,使用事务时,没有两个动作可以针对同一个项目。我不认为这就是你要找的。

但是,您可以在常规操作中使用条件检查。例如,从文档中,

aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --update-expression "SET Price = Price - :discount" \
    --condition-expression "Price > :limit" \
    --expression-attribute-values file://values.json

将执行以下操作:

  • 获取具有给定 ID 的项目
  • 阅读价格并对照它检查条件
  • 如果满足条件,则相应更新

如果不满足条件,则查询将失败并显示特定代码。

  • 请注意,这update实际上是一个 upsert
  • 您必须事先知道ID要查找的项目的名称(实际上,您必须知道哈希键。它可以是 ID、用户名或您选择的任何内容)
  • 另外,请注意,这是一个独特的查询,因此是完全并发安全的。

推荐阅读