【问题标题】:How to put the item in DynamoDB with conditional expression that is not Primary Key如何使用不是主键的条件表达式将项目放入 DynamoDB
【发布时间】:2021-01-26 01:43:20
【问题描述】:

生成一个随机的uuid 值后,我继续将其分配给item.uuid

let uuid = uuidv4();
let title = "Title 100"
let item = {
  uuid: uuid,
  title: title  
};

对于主键为 item.uuid 属性的 Dynamodb 表,我将项目添加到表中:

let TABLE_NAME = "My Table Name";
let options = {};

let promise = dbClient.put_item({ Item: item, TableName: TABLE_NAME, ...options });

新项目被插入到 Dynamodb 表中,主键 uuid 之前生成。

接下来,我想在同一个表中添加另一个项目,具有相同的“title 101”标题:

let uuid = uuidv4();
let title = "title 101"

let item = {
  uuid: uuid,
  title: title  
};

(这两个项目将具有相同的title,但不同的uuid 用作表中的主键)。

由于我想确定,只有在没有其他项目具有相同的“title 101”标题时才会添加此项目,我使用ConditionExpression

let options = {
    ConditionExpression: "#title <> :title",
    ExpressionAttributeNames: { 
        "#title": "title" 
     },
    ExpressionAttributeValues: {
        ":title" : "title 101"
    }
}

let promise = dbClient.put_item({ Item: item, TableName: TABLE_NAME, ...options });
promise
.then(res => {
  console.log('--------- SUCCESS --------');
  console.log(res);
  console.log('-----------------');
});

但不管这里使用的是什么ConditionExpression,DynamoDB 都会继续添加一个具有相同title 值的新项目。

有没有办法在不是主键的属性(字段)上使用条件表达式?

【问题讨论】:

  • 在我看来,title 需要独一无二。为什么不将其作为主键并将 UUID 添加为非键属性。如果严格需要通过 UUID 查找,请在 UUID 上添加 GSI。然后你可以使用attribute_not_exists(#title) 来保证你不会覆盖标题。

标签: javascript python typescript amazon-web-services amazon-dynamodb


【解决方案1】:

Condition Expressions仅适用于更新/删除(不适用于创建),即如果给定主键(PartitionKey + HashKey)的项目已经存在,则检查条件表达式的结果,如果返回true则继续。我们仍然需要传递整个主键。

我们可以尝试使用scan + filter,但我们最终会读取整个表以找到匹配非键属性的行,这很有效,如果表很大,将花费一大笔钱。

所以,在这种情况下,最好的办法是在 title 上添加一个全局二级索引并运行两个单独的查询,首先按标题查询 GSI 以确定是否存在匹配标题的记录,如果不存在则 put-item。

【讨论】:

  • 这里当然会有竞争条件,可能会导致标题重复。您也许可以通过包含 ConditionCheck 的事务来解决这些问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-15
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
相关资源
最近更新 更多