我正在尝试使用新的适用于 NodeJS 的 AWS SDK V3 在 NodeJS 中进行基本的数据库更新操作。
我尝试更新的数据对象如下所示:
{
auth: { BOOL: false },
username: { S: 'siegbert' },
secondsLeft: { N: 49985 },
userid: { S: '123456' }
}
在同一个文件中,我已经使用 SDK V3 成功完成了 GetItemCommand。
不幸的是,当使用AWS SDK v3时,我不断收到一个非常奇怪的错误,当使用SDK v2时,完全相同的参数似乎有效。我尝试查看文档,但更新操作尚未得到很好的记录。
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;
}
这基本上会抛出
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
当使用完全相同的参数但使用 SDK v2 时,它可以工作:
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));
}
});
任何有关如何使用 SDK V3 进行更新的帮助将不胜感激!
一些更正:
user.userid.S
而是传递整个 user.userid
。由于它无法确定类型,因此它假设为一个数组并尝试获取数组的第一个元素并导致该错误。secondsLeft: { N: "49985" }
这是更新后的代码。
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);
});
使用
DynamoDBDocumentClient
模块中的 lib-dynamodb
更容易:
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()
(这可以作为独立的节点脚本运行)
您可以使用
@aws-sdk/lib-dynamodb
包,它是 aws-sdk
v2 风格的更接近的替代品。来自文档:
文档客户端通过抽象属性值的概念,简化了 Amazon DynamoDB 中项目的使用。此抽象注释作为输入参数提供的本机 JavaScript 类型,并将带注释的响应数据转换为本机 JavaScript 类型。
这可能是直接使用
@aws-sdk/client-dynamodb
的更干净的替代方案(并且更容易升级),尽管您仍然需要实例化该客户端作为使用 @aws-sdk/lib-dynamodb
的输入。
这是他们的示例代码:
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",
},
});
我正在努力解决同样的错误,但更新参数结构不同,我试图更新列表属性。
我原来的参数是:
const updateParams = {
...
ExpressionAttributeValues: {
":new_member": [mbr],
},
...
};
我意识到还需要指定列表数据类型描述符,因此:
const updateParams = {
...
ExpressionAttributeValues: {
":new_member": {L:[mbr]},
},
...
};