I am trying to get a basic database update operation to work in nodejs using the new AWS SDK V3 for NodeJS.
The data object that I am trying to update looks like this:
{
auth: { BOOL: false },
username: { S: 'siegbert' },
secondsLeft: { N: 49985 },
userid: { S: '123456' }
}
In the same file I have already succesfully done a GetItemCommand using the SDK V3.
Unfortunately I keep getting a really weird error when using the AWS SDK v3, when using the SDK v2, the exact same params seem to work. I tried looking into the docs but the update operation is not really well documented yet.
var params = {
TableName: "tableXYZ",
Key: {
userid: user.userid.S,
},
UpdateExpression: "SET secondsLeft = :newsecondsLeft",
ExpressionAttributeValues: {
":newsecondsLeft": user.secondsLeft.N,
},
ReturnValues: "UPDATED_NEW"
};
try {
const data = await dbclient.send(new UpdateItemCommand(params));
console.log("data:" + JSON.stringify(data));
return true;
} catch (error) {
console.error(error);
return false;
}
This basically throws
TypeError: Cannot read property '0' of undefined
at Object.AttributeValue.visit (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\models\models_0.js:1101:40)
at XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\protocols\Aws_json1_0.js:5074:20
at Array.reduce (<anonymous>)
at serializeAws_json1_0ExpressionAttributeValueMap (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\protocols\Aws_json1_0.js:5068:34)
at serializeAws_json1_0UpdateItemInput (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\protocols\Aws_json1_0.js:6067:40)
at Object.serializeAws_json1_0UpdateItemCommand (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\protocols\Aws_json1_0.js:474:27)
at serialize (XX\node_modules\@aws-sdk\client-dynamodb\dist\cjs\commands\UpdateItemCommand.js:42:30)
at XX\node_modules\@aws-sdk\middleware-serde\dist\cjs\serializerMiddleware.js:5:27
at XX\node_modules\@aws-sdk\middleware-logger\dist\cjs\loggerMiddleware.js:6:28
When using the exact same params but with the SDK v2, it works:
var docClient = new AWS.DynamoDB.DocumentClient();
docClient.update(params, function (err, data) {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data, null, 2));
}
});
Any help on how to use the SDK V3 for the update would be appreciated!
Couple of corrections:
user.userid.S
pass entire user.userid
. Since its not able to determine the type, it is assuming as an array and trying to get the first element of the array and resulting in that error.secondsLeft: { N: "49985" }
Here is the updated code.
const { DynamoDB, UpdateItemCommand } = require("@aws-sdk/client-dynamodb");
const dbclient = new DynamoDB({ region: "us-east-1" });
const user = {
auth: { BOOL: false },
username: { S: "siegbert" },
secondsLeft: { N: "49985" },
userid: { S: "123456" },
};
var params = {
TableName: "tableXYZ",
Key: {
id: user.userid,
},
UpdateExpression: "SET secondsLeft = :newsecondsLeft",
ExpressionAttributeValues: {
":newsecondsLeft": user.secondsLeft,
},
ReturnValues: "UPDATED_NEW",
};
dbclient
.send(new UpdateItemCommand(params))
.then((result) => {
console.log("data:" + result);
})
.catch((err) => {
console.log("err", err);
});
You can use the @aws-sdk/lib-dynamodb
package, which is a closer replacement to the v2 style of aws-sdk
. From the documentation:
The document client simplifies working with items in Amazon DynamoDB by abstracting away the notion of attribute values. This abstraction annotates native JavaScript types supplied as input parameters, as well as converts annotated response data to native JavaScript types.
This is perhaps a cleaner alternative (and easier to upgrade to) to using @aws-sdk/client-dynamodb
directly, although you will still need to instantiate that client as an input to using @aws-sdk/lib-dynamodb
.
Here is their example code:
import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; // ES6 import
// const { DynamoDBClient } = require("@aws-sdk/client-dynamodb"); // CommonJS import
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb"; // ES6 import
// const { DynamoDBDocumentClient, PutCommand } = require("@aws-sdk/lib-dynamodb"); // CommonJS import
const client = new DynamoDBClient({});
const ddbDocClient = DynamoDBDocumentClient.from(client);
await ddbDocClient.put({
TableName,
Item: {
id: "2",
content: "content from DynamoDBDocument",
},
});
Using the DynamoDBDocumentClient
from the lib-dynamodb
module makes it easier:
import {DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";
const test = async () => {
const client = new DynamoDBClient({region: 'eu-west-1'})
const params = {
TableName: "tableXYZ",
Item:
{
userid: 'userId',
...user
}
}
const docClient = DynamoDBDocumentClient.from(client);
try {
const response = await docClient.send(new PutCommand(params))
console.log(response)
} catch (e) {
console.error(e)
}
}
test()
(this can be run as a stand-alone node script)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With