如何正确使用list_append在DynamoDB中保持值唯一?

Roi*_*jat 6 node.js amazon-dynamodb

在以下代码中,即使联系人联系人属性已存在,也将添加到该联系人属性中。但是我想防止重复,因为两次有相同的联系没有意义。我试图使用包含没有成功。您对我该如何处理有任何想法吗?

const contact = event.contactId
const params = {
    TableName,
    Key: {
        userId: event.userId
    },
    ReturnValues: 'UPDATED_NEW',
    UpdateExpression: 'set #contacts = list_append((if_not_exists(#contacts, :empty_list), :contact)',
    ExpressionAttributeNames: {
        '#contacts': 'contacts'
    },
    ExpressionAttributeValues: {
        ':contact': [contact],
        ':empty_list': []
    }
} // TODO: Must be unique IDs

dynamodb.update(params, (err, data) => {
    if (err) {
        console.log(err)
        callback(err)
    } else {
        console.log(data)
        const response = {
            statusCode: 200,
            message: "Successfully added contact " + contact,
            updatedContacts: data.Attributes.contacts
        }
        callback(null, response)
    }
})
Run Code Online (Sandbox Code Playgroud)

Mat*_*ope 11

据我所知,您需要使用 aSet而不是 aList的联系人 ID 来实现您在一次调用 DynamoDB 中想要的。话虽如此,有两种方法可以使用 完成它,Set如果您在保存新联系人之前可以阅读,则可以使用列表来完成此操作。

选项1

DynamoDB 支持使用ADDfor Set 属性,并且 Set 将保证不存在重复的 ID。您可以使用ADD以静默方式成功,而不会使用此方法导致重复联系。

如果您使用ADD,您的更新表达式将是

ADD #contacts :contact
Run Code Online (Sandbox Code Playgroud)

无论您的联系人 ID 是数字还是字符串,此方法都将起作用。

选项 2

如果联系人已经存在,请使用条件表达式来防止添加联系人。DynamoDB 有一个contains(path, operand)支持 String 和 StringSet 属性的函数。

您将使用与选项 1 中相同的更新表达式,其条件表达式为

attribute_not_exists(#contacts) OR NOT contains(#contacts, :contact)
Run Code Online (Sandbox Code Playgroud)

此选项会让您知道该联系人已经存在,因为如果该联系人已经存在,您将收到ConditionalCheckFailed来自 DynamoDB的响应。

选项 3

首先List从 DynamoDB读取当前联系人。在您的应用程序中验证您不会添加重复项。如果新联系人是重复的,则您无事可做。如果联系人是重复的,那么您可以使用这些表达式保存更新的联系人列表

UpdateExpression: “SET #contacts = :updatedContacts”
ConditionExpression: "#contacts = :oldContacts”
Run Code Online (Sandbox Code Playgroud)

在这种情况下,:oldContacts应该是您最初从 DynamoDB 读取的列表。

这种方法的缺点是对列表的并发更新可能导致有效更新失败。

选项 4

这是所有方法中最复杂的。您可以version为表中的项目添加一个属性,并且与选项 3 一样,您首先读取该项目,验证新联系人不是重复的,然后进行条件写入。但是,在这种情况下,您的条件写入将包括

UpdateExpression: “SET #contacts = :updatedContacts, #version = :newVersion”,
ConditionExpression: “#version = :oldVersion”
Run Code Online (Sandbox Code Playgroud)

这被称为乐观锁定。虽然不是 JavaScript SDK 的一部分,但在这种情况下,您可以自行实现它很简单。

结束语

您应该知道,选项 3 和 4 不适用于在多个区域同时更新的全局表。选项 2 可能无法通知您在相同条件下尝试添加重复项,但它仍将保证不存在重复项。(全局表在区域之间最终是一致的,因此条件表达式可能对一个区域评估为真,但对另一个区域则不然。)

最后,如果您想了解有关可在条件或更新表达式中使用的任何函数的更多详细信息,您可能会发现比较运算符和函数参考很有帮助。

  • 我想是的,但我不知道如何。由于我无法创建一个空集,我如何在用户的个人资料创建中声明一个?它需要为空,因为在添加任何联系人之前需要创建用户。 (2认同)