🔥
[AWS] StepFunctionsのMAP内でDynamoDB updateItemを動かそうとしたらドハマりした話
前提条件
- Json形式のデータに含まれるキーと値のリストをDynamoDBに入力する。
- StepFunctionsの機能のみで実現する。
発生した問題
最初の構築
MAPとUpdateItemだけのシンプルなステートマシンをGUIで作成する。
キーと値はid/samplevalueとするため、この状態で定義ファイルは以下のようになる。
{
"QueryLanguage": "JSONata",
"Comment": "A description of my state machine",
"StartAt": "Map",
"States": {
"Map": {
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "INLINE"
},
"StartAt": "DynamoDB UpdateItem",
"States": {
"DynamoDB UpdateItem": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:updateItem",
"Arguments": {
"TableName": "MyDynamoDBTable",
"Key": {
"id": {
"S": "$.id"
}
},
"UpdateExpression": "SET samplevalue = :myValueRef",
"ExpressionAttributeValues": {
":myValueRef": {
"S": "$.samplevalue"
}
}
},
"End": true
}
}
},
"End": true
}
}
}
問題
自動生成だからこれで動くだろうと思ったら、変数の中身が反映されず次のようなレコードが追加されてしまった。
id | samplevalue |
---|---|
$.id | $.samplevalue |
これに関しては、"S"を、"S.$"に変更するといいよとChatGPTやQが教えてくれるのだが、その変更をすると今度は次のように怒られる。
The field "S.$" is not supported by Step Functions. Did you mean 'SS'? /States/Map/ItemProcessor/States/DynamoDB UpdateItem/Arguments
さらにいろいろ調べていくと、ArgumentsではなくParametersを使うパターンが見つかったので書き換えてみるが、今度は次のエラーが出た。
ワークフローに 3 件のエラーが見つかりました。 このページにとどまり、エラーを修正しますか?
DynamoDB UpdateItem (Arguments.TableName): Value is mandatory.
DynamoDB UpdateItem (Arguments.Key): Value is mandatory.
DynamoDB UpdateItem (Parameters): Field is not available.
AIの言うとおりに修正を試すが複数のパターンをループするだけで一向に解決しなかった。
解決
ArgumentsとParametersの違い
これはQueryLanguageがJSONataかJSONPathかによって異なる。JSONataの方が高機能だが、MAPではJSONPathが推奨されるらしい。
今回はデフォルトでJSONataが選択されていたため、Parametersが使えず、その中で変数を指定する方法も従来のものが使えなかった、ということになる。
一番簡単なのは、最初にステートマシンクエリ言語でJSONPathを選ぶことでした。
最終的な記載
{
"QueryLanguage": "JSONPath",
"Comment": "A description of my state machine",
"StartAt": "Map",
"States": {
"Map": {
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "INLINE"
},
"StartAt": "DynamoDB UpdateItem",
"States": {
"DynamoDB UpdateItem": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:updateItem",
"Parameters": {
"TableName": "Stables",
"Key": {
"id": {
"S.$": "$$.Map.Item.id"
}
},
"UpdateExpression": "SET samplevalue = :myValueRef",
"ExpressionAttributeValues": {
":myValueRef": {
"S.$": "$$.Map.Item.samplevalue"
}
}
},
"End": true
}
}
},
"End": true
}
}
}
QueryLanguageを変更することでS.$が使えるようになるため、無事文字列型でidを指定することができるようになったため、変数の書き込みが可能になった。
※実際に使用した環境とは列名などを変えているため、このまま動作するかはわかりません。
Discussion