セッションアトリビュートの永続化についてではなく、ユーザー間で共有するデータをDynamoDBに保存してアクセスする方法についてです。
例えば、トリビアスキルなどで、たくさんのトリビアデータをJSファイルに書いておくとコードと一体化してしまいますが、データベースに切り離しておくことでメンテナンスが容易になります。
また、ゲームスキルで「あなたは〇人目の達成者です」といった記録にも必要になると思います。
AWS.DynamoDB.DocumentClientを使う
結論としてはそれだけなんですが、ASK-SDK2でそのまま使えるサンプルが見つからなかったので…。
例として、DynamoDBには 'Trivias' というテーブルがあり、プライマリキーに 'id' という数値、項目には 'trivia' という、発話させたい文字列が入っていることとします。トリビアは100個あり、スキルを起動するとどれか一つをランダムで教えてくれるものとします。
lambdaのランタイムは Node.js 8.10 です。
const awsSDK = require('aws-sdk')
const docClient = new awsSDK.DynamoDB.DocumentClient()
const getTrivia = async randomId => {
var params = {
TableName: 'Trivias',
Key:{
id: randomId
}
}
return docClient.get(params).promise()
}
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest'
},
// async をつけないとawaitは使えない
async handle(handlerInput) {
const randomId = Math.floor(Math.random() * 100)
const result = await getTrivia(randomId) // awaitで同期的に結果を受け取る
const item = result.Item // Itemというプロパティにデータが入ってる
return handlerInput.responseBuilder
.speak(item.trivia)
.getResponse()
}
};
DocumentClientのget()などのメソッドには第二引数でコールバック関数を渡すことになっているのですが、それだとどうやってgetResponse()をリターンすればいいかわかりませんでした。
しかしコールバックを渡さずpromise()というメソッドを呼び出すとPromise化できるようで、さらにNode.jsのバージョンを8.1にすることでasync/awaitが使え、シンプルに書けました。
本記事ではget()メソッドだけ使っていますが、更新などその他メソッドについては
【詳解】JavascriptでDynamoDBを操作する
で詳しく紹介されています。 (コールバック部分を書き換えましょう)
なお自作のスキルでは、
- トリビアスキル「アメリカ映画の名セリフベスト100」でちょうど本記事のように100個の情報が入ったDyanamoDBからランダムに取り出し
- 脱出ゲームスキル「暗闇のサンタクロース」で脱出成功者と失敗者の数をDyanamoDBに記録
を実現しています。