You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS SDK v2转v3 DynamoDB查询方法出错,请求排查问题

AWS SDK v2迁移到v3后DynamoDB查询报错:TypeError: Cannot read properties of undefined (reading '0')

我有一个可正常运行的AWS SDK v2 DynamoDB记录查询方法,但迁移到v3后方法运行失败,报错信息如下:

C:\Users\xxx\Desktop\_REPOS\_PERSONAL\yyy\backend\node_modules\@aws-sdk\client-dynamodb\dist-cjs\index.js:1004 
return visitor._(value.$unknown[0], value.$unknown[1]); 
^ TypeError: Cannot read properties of undefined (reading '0')

报错的极简v3示例代码

import { DynamoDBClient, QueryCommand, QueryCommandInput } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

export const marshallOptions = {
    convertEmptyValues: false, // false, by default.
    removeUndefinedValues: true, // false, by default.
    convertClassInstanceToMap: true, // false, by default.
  };
  
export const unmarshallOptions = {
    wrapNumbers: false, // false, by default.
  };
(async()=>{
const dynamoDBClient = new DynamoDBClient({ region: "us-east-1" });
const dynamoDocClient = DynamoDBDocumentClient.from(dynamoDBClient, 
{
  marshallOptions,
  unmarshallOptions,
}
);

    let params:QueryCommandInput={
    TableName: 'notesV2Table',
    IndexName: 'topic-index',
    KeyConditionExpression: '#ty = :val',
    ExpressionAttributeNames: { '#ty': 'topic' },
    ExpressionAttributeValues: { ':val': 'Dynamo' } as any
  }
  
  //return await dynamoDocClient.send(new QueryCommand(params));
  return await dynamoDBClient.send(new QueryCommand(params));

})()

运行失败的v3代码

export const marshallOptions = {
    // Whether to automatically convert empty strings, blobs, and sets to `null`.
    convertEmptyValues: false, // false, by default.
    // Whether to remove undefined values while marshalling.
    removeUndefinedValues: true, // false, by default.
    // Whether to convert typeof object to map attribute.
    convertClassInstanceToMap: true, // false, by default.
  };
  
export const unmarshallOptions = {
    // Whether to return numbers as a string instead of converting them to native JavaScript numbers.
    wrapNumbers: false, // false, by default.
  };

// Create a DynamoDB client
const dynamoDBClient = new DynamoDBClient({ region: "us-east-1" });

  // Full document client
export const dynamoDocClient = DynamoDBDocumentClient.from(dynamoDBClient, {
  marshallOptions,
  unmarshallOptions,
});

export var queryNotesByTopic = async function (event: any) {
  try {
    console.log(`event`, event);
    if (event.hasOwnProperty("obj")) event = event.obj;
    console.log(`queryNotesByTopic object: `, event);
    //let topic = event.queryStringParameters["topic"] || null; //GET param

    let topic = event["topic"];
    if (!topic) throw `invalid topic ${topic}`;
    console.log(`query for each row with id: ${topic}`);

    //this matches any cards with the id 'Dynamo'
    var params = {
      TableName: TABLE_NAME,
      IndexName: "topic-index",
      KeyConditionExpression: "#ty = :val",
      ExpressionAttributeNames: {
        "#ty": "topic",
      },
      ExpressionAttributeValues: {
        ":val": topic,
      },
    };
    console.log(params);

    return await dynamoDocClient.send(new QueryCommand(params));
  } catch (e) {
    throw e;
  }
};

可正常运行的v2代码

export var queryNotesByTopic = async function (event: any) {
  const docClient = new AWS.DynamoDB.DocumentClient({
    apiVersion: "2012-08-10",
  });
  try {
    console.log(`event`, event);
    if (event.hasOwnProperty("obj")) event = event.obj;
    console.log(`queryNotesByTopic object: `, event);
    //let topic = event.queryStringParameters["topic"] || null; //GET param

    let topic = event["topic"];
    if (!topic) throw `invalid topic ${topic}`;
    console.log(`query for each row with id: ${topic}`);

    //this matches any cards with the id 'Dynamo'
    var params = {
      TableName: TABLE_NAME,
      IndexName: "topic-index",
      KeyConditionExpression: "#ty = :val",
      ExpressionAttributeNames: {
        "#ty": "topic",
      },
      ExpressionAttributeValues: {
        ":val": topic,
      },
    };
    console.log(params);

    return await docClient.query(params).promise();
  } catch (e) {
    throw e;
  }
};

问题原因与修复方案

问题核心是DynamoDBClient和DynamoDBDocumentClient的参数格式不兼容:

  • 原生DynamoDBClient要求ExpressionAttributeValues必须使用DynamoDB的类型格式(比如{ S: 'Dynamo' }),不能直接传普通JavaScript类型。
  • DynamoDBDocumentClient则和v2的DocumentClient用法一致,支持直接传普通JavaScript类型,内部会自动完成类型转换。

针对极简示例的修复

示例中注释掉了正确的dynamoDocClient.send调用,改用原生DynamoDBClient发送请求,导致参数格式不匹配。恢复注释的代码即可解决:

return await dynamoDocClient.send(new QueryCommand(params));

针对实际v3代码的检查与修复

当前代码写法理论上可以正常运行,但需要确认以下两点:

  1. TABLE_NAME已正确定义,没有出现undefined的情况。
  2. topic的值是有效字符串,而非undefined或其他非字符串类型,确保DynamoDBDocumentClient能正常完成类型转换。

如果一定要使用原生DynamoDBClient,则需要手动将参数转换为DynamoDB类型格式,示例:

ExpressionAttributeValues: { ':val': { S: topic } }

内容的提问来源于stack exchange,提问作者Rilcon42

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 03:34:58