【问题标题】:Why "documentClient.put" is doing UPDATE instead of INSERT in DynamoDB?为什么“documentClient.put”在 DynamoDB 中执行 UPDATE 而不是 INSERT?
【发布时间】:2020-12-21 21:35:15
【问题描述】:

我有一个简单的逻辑,我想使用AWS.DynamoDB.DocumentClient 在表中记录INSERT。下面是我正在使用的代码。在这里,我注意到.put 正在更新记录,但不知道为什么。

在检查 CW 中的日志时,我没有看到任何错误,所以不确定我在这里遗漏了什么。

代码:

async addEvent(incomingModel: MyModel): Promise <MyModel> {
    const dynamoModel: MyModel = {
        fieldOne: incomingModel.fieldOne,
        fieldTwo: incomingModel.fieldTwo,
        "One#two#three": `${incomingModel.one}#${incomingModel.two}#${incomingModel.three}`,
        fieldThree: incomingModel.fieldThree,
        fieldFour: incomingModel.fieldFour,
    };

    var params = {
        TableName: 'Table',
        Item: dynamoModel,
    };

    return this.documentClient
        .put(params)
        .then((data) => {
            this.logger.debug(
                "Response received from Dynamo after adding an incomingModel",
                data,
                this.constructor.name,
            );

            return data as MyModel;
        })
        .catch((error) => {
            const errorMessage = JSON.stringify(error);
            this.logger.error(
                `Error creating incomingModel with body of ${errorMessage}`,
                error,
                this.constructor.name,
            );
            throw error;
        });
}

【问题讨论】:

    标签: node.js typescript amazon-web-services amazon-dynamodb documentclient


    【解决方案1】:

    这是put 操作的预期行为。来自docs(强调我的):

    创建新项目,或用新项目替换旧项目。如果指定表中已经存在与新项具有相同主键的项,则新项完全替换现有项。

    【讨论】:

    • PutItem 确实如此,但这里我使用的是Put。在这里,docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/…
    • 嗯,我不确定我是否注意到了差异。 Put API 说“创建一个新项目,或通过委托给AWS.DynamoDB.putItem() 用新项目替换旧项目”。我不知道你的主键是什么样的,但也许这就是这里发生的事情。 DynamoDB 认为您正在对旧项目进行操作并委托给 putItem。你期待什么行为?我假设您希望使用 put 操作创建(未更新)记录。这个假设正确吗?
    • 是的。这就是期望。
    • 如果您对 DynamoDB 中已存在的项目执行put 操作,则客户端的行为与预期相同。如果不存在具有该主键的项目,put 将创建一个新项目。如果该项目确实存在,它将委托给putItem,然后它将完全替换现有项目。主键在 DynamoDB 中是唯一的,因此没有两个项目可以具有相同的主键。我看不出这段代码 sn-p 有什么问题。
    • 我想通了。在这里,我的主键不是唯一的,所以当结合主键 + sortKey 时它可以工作。这是我今天了解到Put 的新行为。感谢您的建议。
    【解决方案2】:

    正如 Seth 所说,这是 DynamoDb 的默认行为。

    为了避免更新,您可以做的是利用“ConditionExpression”。在我的示例中,我将“PK”命名为 HashKey,将“SK”命名为 RangeKey:

    async function put(Item, TableName){
        const params = {
            TableName,
            Item,
            ExpressionAttributeNames : {
                '#pk' : 'PK',
                '#sk' : 'SK',
            },
            ConditionExpression : 'attribute_not_exists(#pk) AND attribute_not_exists(#sk)',
        };
        
        const result = await documentClient.put(params).promise();
        
        // ... do the rest....
    
    }
    

    如果项目已经存在(两个键都匹配),则交易将失败,并给出"ConditionalCheckFailedException: The conditional request failed"

    我希望这会有用!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-11
      • 1970-01-01
      • 2012-03-22
      • 2011-06-11
      • 2021-10-20
      • 2012-06-16
      相关资源
      最近更新 更多