如何使用非主键的条件表达式将项目放入 DynamoDB

How to put the item in DynamoDB with conditional expression that is not Primary Key

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

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

使用 Dynamodb table,其中主键是 item.uuid 属性,我将项目添加到 table 中:

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

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

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

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

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

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

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

因为我想确定,只有当没有其他项目具有相同的“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 值的新项目。

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

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

我们可以尝试使用 scan + filter,但我们最终会读取整个 table 以找到与非键控属性匹配的行,这是高效的并且如果 table 很大。

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