Why "documentClient.put" is doing UPDATE instead of INSERT in DynamoDB?

4.5k Views Asked by At

I have a simple logic where I want to INSERT record in the table using AWS.DynamoDB.DocumentClient. Below is code which I am using. Here, I am noticing that .put is updating the record and not sure why.

While checking the logs in CW, I am not seeing any error so not sure what am I missing here.

Code:

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;
        });
}
2

There are 2 best solutions below

5
On BEST ANSWER

This is the expected behavior of the put operation. From the docs (emphasis mine):

Creates a new item, or replaces an old item with a new item. If an item that has the same primary key as the new item already exists in the specified table, the new item completely replaces the existing item.

0
On

As Seth mentioned, this is the default behaviour of DynamoDb.

What you can do to avoid updates is make use of the "ConditionExpression". Here in my example, I named 'PK' to the HashKey and 'SK' to the 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....

}

If the item already exist (Both keys matches) the transaction will fail giving a "ConditionalCheckFailedException: The conditional request failed"

I hope this will be useful!