AWS NodeJS SDK V3 DynamoDB UpdateItem - TypeError:无法读取未定义的属性“0”

Dus*_*ron 5 amazon-web-services amazon-dynamodb aws-sdk-nodejs

我正在尝试使用适用于 NodeJS 的新 AWS SDK V3 在 nodejs 中进行基本的数据库更新操作。

我尝试更新的数据对象如下所示:

{
  auth: { BOOL: false },
  username: { S: 'siegbert' },
  secondsLeft: { N: 49985 },
  userid: { S: '123456' }
}
Run Code Online (Sandbox Code Playgroud)

在同一个文件中,我已经成功地使用 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;
    }
Run Code Online (Sandbox Code Playgroud)

这基本上抛出

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
Run Code Online (Sandbox Code Playgroud)

当使用完全相同的参数但使用 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));
    }
});
Run Code Online (Sandbox Code Playgroud)

任何有关如何使用 SDK V3 进行更新的帮助将不胜感激!

Cir*_*yon 10

使用模块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()
Run Code Online (Sandbox Code Playgroud)

(这可以作为独立的节点脚本运行)

  • 谢谢。我从 @aws-sdk/client-dynamodb 导入了 QueryCommand,而不是从 @aws-sdk/lib-dynamodb 导入 (4认同)

小智 8

您可以使用该@aws-sdk/lib-dynamodb包,它更接近 v2 风格的aws-sdk. 从文档中:

文档客户端通过抽象属性值的概念,简化了 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",
  },
});
Run Code Online (Sandbox Code Playgroud)


Bal*_*ala 5

几个更正:

  • 传递值时,我们需要传递带有类型的对象。所以,而不是user.userid.S通过整个user.userid. 由于它无法确定类型,因此它假设为一个数组并尝试获取数组的第一个元素并导致该错误。
  • 数字值,应该简单地作为“N”类型的字符串值传递,比如 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);
  });
Run Code Online (Sandbox Code Playgroud)