環境
- Nodejs
- AWS Lambda
- AWS DynamoDB
はじめに
DynamoDBではパーティションキーもしくはレンジキーを使用してしか基本的には抽出が出来ないのですが、任意のキーを元に抽出を行いたいという時は、Global Secondary Index(以下GSI)を使用する事で任意のキーでレコードを抽出することが出来ます。
注意点
以下の点に気をつける必要があります。
- GSIは1テーブルにつき20件までしか作成出来ない
- GSIのキーに指定出来るカラムのデータ型は文字列、数値、バイナリのいずれかである必要があります
- Serverless Frameworkではまだそこまで自由なGSIは作成出来ないようなので、DynamoDBコンソールからGSIを作成する必要がある(ハッシュキー or レンジキー以外でのGSIの作成がうまくいかなかった)
例えばboolean型のカラムをキーにGSIは作成出来ません(私がやろうとしていました...)
参考情報:
前提
適当ですが、以下のようなUsers
テーブルがあるとします。
カラム名 | データ型 | キー |
---|---|---|
username | string | hash |
age | integer | range |
isPremier | integer |
isPremier
カラムは0
か1
が整数で入るとします。
そしてisPremier
が0
のレコードを全件取得したいというのが実現したいことです。
動作サンプルの手順
- AWS DynamoDB ConsoleからGSIを作成
- queryを行うLambdaを作成
AWS DynamoDB ConsoleからGSIを作成
AWSのDynamoDB Consoleページ > テーブル > インデックス にアクセスします
そしてインデックスの作成
ボタンから新規のGSIを以下のように作成します。
queryを行うLambdaを作成
NodejsでLambda関数を作成します。
先ほど作成したGSIの以下の情報を使用します。
- テーブル名:
Users
- インデックス名:
isPremier-index
抽出条件はisPremier
が0のレコードを全件取得
const AWS = require('aws-sdk')
const DynamoDB = new AWS.DynamoDB.DocumentClient({region: "ap-northeast-1"})
module.exports.hello = async (event, context) => {
try {
const params = {
TableName: 'Users', // テーブル名
IndexName: 'isPremier-index', // 作成したGSI名
KeyConditionExpression: '#indexKey = :indexValue', // 条件を指定
ExpressionAttributeNames : {
"#indexKey" : 'isPremier' // GSIの作成時に指定したキー名を設定
},
ExpressionAttributeValues: {
':indexValue': 0 // isPremierの0を抽出
}
}
let items = [] // 抽出したレコードを格納するための空の配列を定義
const query = async () => {
console.log('start query')
let result = await DynamoDB.query(params).promise()
items.push(...result.Items)
// LastEvaluatedKeyが存在していたら再帰的にqueryを実行
if(result.LastEvaluatedKey){
params.ExclusiveStartKey = result.LastEvaluatedKey
await query()
}
}
await query()
console.log(`Execution result: ${items.length}`)
} catch (err) {
console.error(`[Error]: ${JSON.stringify(err)}`)
return err
}
}
以上で条件にあったレコードを全件取得出来ます。