AWS Step Functionsでは組み込み関数だけで配列のフィルターやスライスができる(AWS CDK v2)
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、AWS Step FunctionsでIntrinsic functions(組み込み関数)だけで配列のフィルターやスライス(部分選択)をする方法が便利だったので共有したいと思います。
やってみた
検証環境の作成をAWS CDK v2(TypeScript)で行います。次のようなCDKスタックを作成します。
import { Construct } from 'constructs'; import { aws_stepfunctions, Stack, StackProps } from 'aws-cdk-lib'; export class ProcessStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); const firstTask = new aws_stepfunctions.Pass(this, 'firstTask', { parameters: { jsonPath1: aws_stepfunctions.JsonPath.stringAt('$.store.book[*].author'), jsonPath2: aws_stepfunctions.JsonPath.stringAt('$..author'), jsonPath3: aws_stepfunctions.JsonPath.stringAt('$.store.*'), jsonPath4: aws_stepfunctions.JsonPath.stringAt('$.store..price'), jsonPath5: aws_stepfunctions.JsonPath.stringAt('$..book[2]'), jsonPath6: aws_stepfunctions.JsonPath.stringAt('$..book[(@.length-1)]'), jsonPath7: aws_stepfunctions.JsonPath.stringAt('$..book[-1:]'), jsonPath8: aws_stepfunctions.JsonPath.stringAt('$..book[0,1]'), jsonPath9: aws_stepfunctions.JsonPath.stringAt('$..book[:2]'), jsonPath10: aws_stepfunctions.JsonPath.stringAt('$..book[?(@.isbn)]'), jsonPath11: aws_stepfunctions.JsonPath.stringAt('$..book[?(@.price<10)]'), jsonPath12: aws_stepfunctions.JsonPath.stringAt('$..*'), }, }); new aws_stepfunctions.StateMachine(this, 'stateMachine', { stateMachineName: 'stateMachine', definition: firstTask, }); } }
上記をCDK Deployしてスタックをデプロイします。これにより次のDefinitionのステートマシンが作成されます。
{ "StartAt": "firstTask", "States": { "firstTask": { "Type": "Pass", "Parameters": { "jsonPath1.$": "$.store.book[*].author", "jsonPath2.$": "$..author", "jsonPath3.$": "$.store.*", "jsonPath4.$": "$.store..price", "jsonPath5.$": "$..book[2]", "jsonPath6.$": "$..book[(@.length-1)]", "jsonPath7.$": "$..book[-1:]", "jsonPath8.$": "$..book[0,1]", "jsonPath9.$": "$..book[:2]", "jsonPath10.$": "$..book[?(@.isbn)]", "jsonPath11.$": "$..book[?(@.price<10)]", "jsonPath12.$": "$..*" }, "End": true } } }
次の入力を指定してステートマシンを実行します。
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } }
すると実行が成功しました。firstTask
のOutputでは各JSONPathの適用結果が取得できています。
各JSONPathと適用結果
各JSONPathとその適用結果をそれぞれ見てみます。
JSONPath1
store
内のすべてのbook
のauthor
を取得。
// JSONPath $.store.book[*].author // Result [ "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" ]
JSONPath2
すべてのauthor
を取得。
// JSONPath $..author // Result [ "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" ]
JSONPath3
store
内のすべてを取得。
// JSONPath $.store.* // Result [ [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], { "color": "red", "price": 19.95 } ]
JSONPath4
store
内のすべてのprice
を取得。
// JSONPath $.store..price // Result [ 8.95, 12.99, 8.99, 22.99, 19.95 ]
JSONPath5
3番目のbook
を取得。
// JSONPath $..book[2] // Result [ { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 } ]
JSONPath6
順番が最後のbook
を取得。
// JSONPath $..book[(@.length-1)] // Result [ { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ]
JSONPath7
順番が最後のbook
を取得。
// JSONPath $..book[-1:] // Result [ { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ]
JSONPath8
最初の2つのbook
を取得。
// JSONPath $..book[0,1] // Result [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 } ]
JSONPath9
最初の2つのbook
を取得。
// JSONPath $..book[:2] // Result [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 } ]
JSONPath10
isbn
を持つすべてのbook
をフィルター。
// JSONPath $..book[?(@.isbn) // Result [ { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ]
JSONPath11
price
が10
より大きいすべてのbook
をフィルター。
// JSONPath $..book[?(@.price<10)] // Result [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 } ]
JSONPath12
すべての要素を取得。
// JSONPath $..* // Result [ { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } }, [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], { "color": "red", "price": 19.95 }, { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 }, "reference", "Nigel Rees", "Sayings of the Century", 8.95, "fiction", "Evelyn Waugh", "Sword of Honour", 12.99, "fiction", "Herman Melville", "Moby Dick", "0-553-21311-3", 8.99, "fiction", "J. R. R. Tolkien", "The Lord of the Rings", "0-395-19395-8", 22.99, "red", 19.95 ]
できそうで出来なかったこと
ドキュメントではlength()
なるものものありましたが、試してみるとエラーとなり使えませんでした。
jsonPath13: aws_stepfunctions.JsonPath.stringAt('$.store.book.length()'),
Step Functionsでは対応していないようです。
おわりに
AWS Step FunctionsでIntrinsic functions(組み込み関数)だけで配列のフィルターやスライス(部分選択)をする方法が便利だという話でした。
JSONPathめちゃくちゃ便利ですね!ここまで出来るとは思いませんでした。
前回の下記エントリに引き続き、Step Functionsでの便利な配列の処理方法を確認することができて良かったです。
参考
以上