[英]DynamoDB JavaScript PutItemCommand is neither failing nor working
請注意:雖然這個問題提到了 AWS SAM,但它 100% 是一個 DynamoDB JavaScript SDK 問題的核心,任何有使用 AWS DynamoDB 客戶端/SDK 針對 DynamoDB 編寫 JavaScript Lambdas(或任何客戶端應用程序)經驗的人都可以回答。
因此,我使用 AWS SAM 預置了一個具有以下屬性的新 DynamoDB 表:
FeedbackDynamoDB:
Type: AWS::DynamoDB::Table
Properties:
TableName: commentary
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
StreamSpecification:
StreamViewType: NEW_IMAGE
此配置成功創建了一個名為commentary
的 DynamoDB 表。 但是,當我在 DynamoDB web 控制台中查看此表時,我注意到了一些事情:
我不確定這是否會引起任何人的注意,但我想我會包括這些詳細信息,以防我配置不正確。
現在,我有一個 JavaScript (TypeScript) Lambda 實例化一個 DynamoDB 客戶端(使用 JavaScript SDK)並嘗試向該表添加記錄/項目:
// this code is in a file named app.ts:
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { User, allUsers } from './users';
import { Commentary } from './commentary';
import { PutItemCommand } from "@aws-sdk/client-dynamodb";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
const ddbClient = new DynamoDBClient({ region: "us-east-1" });
let status: number = 200;
let responseBody: string = "\"message\": \"hello world\"";
const { id, content, createdAt, providerId, receiverId } = JSON.parse(event.body);
const commentary = new Commentary(id, content, createdAt, providerId, receiverId);
console.log("deserialized this into commentary");
console.log("and the deserialized commentary has content of: " + commentary.getContent());
await provideCommentary(ddbClient, commentary);
responseBody = "\"message\": \"received commentary -- check dynamoDb!\"";
return {
statusCode: status,
body: responseBody
};
} catch (err) {
console.log(err);
return {
statusCode: 500,
body: JSON.stringify({
message: err.stack,
}),
};
}
};
const provideCommentary = async (ddbClient: DynamoDBClient, commentary: Commentary) => {
const params = {
TableName: "commentary",
Item: {
id: {
S: commentary.getId()
},
content: {
S: commentary.getContent()
},
createdAt: {
S: commentary.getCreatedAt()
},
providerId: {
N: commentary.getProviderId()
},
receiverId: {
N: commentary.getReceiverId()
}
}
};
console.log("about to try to insert commentary into dynamo...");
try {
console.log("wait for it...")
const rc = await ddbClient.send(new PutItemCommand(params));
console.log("DDB response:", rc);
} catch (err) {
console.log("hmmm something awry. something....in the mist");
console.log("Error", err.stack);
throw err;
}
};
其中commentary.ts
是:
class Commentary {
private id: string;
private content: string;
private createdAt: Date;
private providerId: number;
private receiverId: number;
constructor(id: string, content: string, createdAt: Date, providerId: number, receiverId: number) {
this.id = id;
this.content = content;
this.createdAt = createdAt;
this.providerId = providerId;
this.receiverId = receiverId;
}
public getId(): string {
return this.id;
}
public getContent(): string {
return this.content;
}
public getCreatedAt(): Date {
return this.createdAt;
}
public getProviderId(): number {
return this.providerId;
}
public getReceiverId(): number {
return this.receiverId;
}
}
export { Commentary };
當我使用此處理程序代碼更新 Lambda 並使用以下 curl 命中 Lambda 時(Lambda 由我可以通過 curl/http 命中的 API 網關 URL 調用):
curl -i --request POST 'https://<my-api-gateway>.execute-api.us-east-1.amazonaws.com/Stage/feedback' \
--header 'Content-Type: application/json' -d '{"id":"123","content":"test feedback","createdAt":"2022-12-02T08:45:26.261-05:00","providerId":457,"receiverId":789}'
我收到以下 HTTP 500 響應:
{"message":"SerializationException: NUMBER_VALUE cannot be converted to String\n
我是否向它傳遞了錯誤的請求正文(在 curl 中),或者我是否需要在app.ts
和/或commentary.ts
中進行一些調整?
有趣的是, DynamoDB API期望項目的數字字段為字符串。 例如:
"N": "123.45"
醫生說;
數字作為字符串通過網絡發送到 DynamoDB,以最大限度地提高跨語言和庫的兼容性。 但是,DynamoDB 將它們視為數學運算的數字類型屬性。
您是否嘗試過將數字參數作為字符串發送輸入,如下所示? (參見providerId
和receiverId
)
{
"id":"123",
"content":"test feedback",
"createdAt":"2022-12-02T08:45:26.261-05:00",
"providerId":"457",
"receiverId":"789"
}
您可以在填充輸入Item
時將這些 ID 轉換為字符串:
providerId: {
N: String(commentary.getProviderId())
},
receiverId: {
N: String(commentary.getReceiverId())
}
您也可以使用.toString()
但如果未設置該字段( null
或undefined
),您會收到錯誤消息。
嘗試使用 promise 來查看結果:
client.send(command).then(
(data) => {
// process data.
},
(error) => {
// error handling.
}
);
您的表設置似乎一切正常,我相信這是 Lambda 與 JS sdk 的異步問題。我猜 Lambda 沒有等待您的代碼並提前退出。 你能包括你完整的 lambda 代碼嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.