使用DataMapper从DynamoDB获取数据时触发运行时错误
扫描操作错误
2023-01-04T20:02:56.603Z 1ef44a6b-8b4f-51c5-bd10-164456efc703 ERROR Invoke Error {
"errorType": "TypeError",
"errorMessage": "this.client.scan(...).promise is not a function",
"stack": [
"TypeError: this.client.scan(...).promise is not a function",
" at ScanPaginator.getNext (/var/task/node_modules/@aws/dynamodb-query-iterator/build/ScanPaginator.js:17:18)",
" at /var/task/node_modules/@aws/dynamodb-query-iterator/build/DynamoDbPaginator.js:60:26"
] }
获取操作错误
{
"errorType": "Runtime.UnhandledPromiseRejection",
"errorMessage": "TypeError: _b.map is not a function",
"reason": {
"errorType": "TypeError",
"errorMessage": "_b.map is not a function",
"stack": [
"TypeError: _b.map is not a function",
" at /var/task/node_modules/@aws-sdk/middleware-user-agent/dist-cjs/user-agent-middleware.js:14:151",
" at async /var/task/node_modules/@aws-sdk/middleware-logger/dist-cjs/loggerMiddleware.js:5:22"
]
},
"promise": {},
"stack": [
"Runtime.UnhandledPromiseRejection: TypeError: _b.map is not a function",
" at process. (file:///var/runtime/index.mjs:1194:17)",
" at process.emit (node:events:513:28)",
" at emit (node:internal/process/promises:149:20)",
" at processPromiseRejections (node:internal/process/promises:283:27)",
" at process.processTicksAndRejections (node:internal/process/task_queues:96:32)"
] }
用到的代码
DTO定义
@table("Configs") export class Configs { @hashKey() configId!: string; @attribute() groupName!: string }
Lambda Handler代码
import {SQSEvent} from "aws-lambda"; import {DynamoDB} from "@aws-sdk/client-dynamodb" import {DataMapper} from "@aws/dynamodb-data-mapper"; import {Configs} from "./models/Configs"; const client = new DynamoDB({region: "us-east-1"}); const mapper = new DataMapper({client}); export const handler = async (sqsEvent: SQSEvent) => { console.log(`Event: ${JSON.stringify(sqsEvent, null, 2)}`); for (let record of sqsEvent.Records) { let messageBody = record.body; console.log("MessageBody: " + messageBody); } const config = new Configs(); for await (const item of mapper.scan(Configs)) { console.log('scan result', item); } console.log("done scanning"); mapper.get(Object.assign(new Configs(), {id: 'MY_ID'})) .then(myItem => { console.log('MyItem from db: ', myItem); }) .catch(err => { console.log("Not found"); }) };
tsconfig.json配置
{ "compilerOptions": { "experimentalDecorators": true, "target": "es2020", "strict": true, "preserveConstEnums": true, "outDir": "./dist/lib", "module": "CommonJS", "declaration": true, "declarationDir": "./dist/types", "sourceMap": false, "moduleResolution":"node", "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "emitDecoratorMetadata": true, "typeRoots": [ "./node_modules/@types" ] }, "exclude": [ "./node_modules", "**/*.test.ts"] }
问题原因与解决办法
核心问题:SDK版本不兼容
@aws/dynamodb-data-mapper 基于AWS SDK v2开发,而你使用的是AWS SDK v3的@aws-sdk/client-dynamodb,两者API逻辑不兼容:
- v2的DynamoDB客户端方法(如
scan)返回的对象自带.promise()方法,v3客户端返回的是命令对象,需用send方法调用,无.promise(),直接触发扫描错误。 _b.map错误也是v3中间件与data-mapper的v2逻辑不兼容导致的。
解决步骤
替换SDK为v2版本
卸载v3客户端,安装v2的aws-sdk:npm uninstall @aws-sdk/client-dynamodb npm install aws-sdk修改Handler中的导入与客户端初始化
调整代码导入和客户端创建逻辑:import {SQSEvent} from "aws-lambda"; // 替换v3导入为v2的AWS SDK import AWS from "aws-sdk"; import {DataMapper} from "@aws/dynamodb-data-mapper"; import {Configs} from "./models/Configs"; // 使用v2的DynamoDB客户端 const client = new AWS.DynamoDB({region: "us-east-1"}); const mapper = new DataMapper({client});修正get操作的属性错误
DTO中哈希键为configId,但代码中用了id: 'MY_ID',会导致无法匹配数据,需改为:mapper.get(Object.assign(new Configs(), {configId: 'MY_ID'})) .then(myItem => { console.log('MyItem from db: ', myItem); }) .catch(err => { console.log("Not found"); })验证依赖版本
确保@aws/dynamodb-data-mapper及其关联依赖(如@aws/dynamodb-data-mapper-annotations)为兼容v2的最新版本,避免版本冲突。
内容的提问来源于stack exchange,提问作者AnOldSoul

