はじめに
本記事ではDynamoDBのGSI(Global Secondary Index)を作成し、Lambdaからクエリを実行する処理を実装していきます。
ゴール
DynamoDBのGSIに対してLambdaからクエリを実行し、パーティションキーとソートキーの条件に一致する項目から、特定の属性値のみを取得します。
下記のようなGSIを作成し、user1 の user_status:activeを取得する処理を実装します。
▼GSI例
| userId(パーティションキー) | timestamp(ソートキー) | user_status | 
|---|---|---|
| user1 | 2024-11-07 | active | 
| user2 | 2024-11-08 | active | 
作るもの
- DynamoDBのテーブル:1つ
- GSI:1つ
 
 - Lambda:1つ
 
書かない事
IAMの権限については本記事では記載しておりません。
1. DynamoDBのテーブルを作成
次の5つの属性を持つテーブルを作成します。
- id (パーティションキー)
 - userId
 - timestamp
 - user_status
 - category
 
2. GSIを作成
次の3つの属性を持つインデックスを作成します。
- userId (GSIのパーティションキー)
 - timestamp (GSIのソートキー)
 - user_status (取得したい属性、Include > 属性名で選択)
 
次の図のようにインデックスタブから想定通りGSIを作成できている事を確認できました。
3. Lambdaを作成
import json
import boto3
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('test-1107-db')
def lambda_handler(event, context):
    body = json.loads(event['body'])
    user_id = body['userId']
    specific_date = body['timestamp']
    
    # GSIを使用したクエリ
    response = table.query(
        # インデックス名
        IndexName='userId-timestamp-index',
        # クエリ条件:userIdとtimestampが一致する項目を検索
        KeyConditionExpression=Key('userId').eq(user_id) & Key('timestamp').eq(specific_date),
        # user_statusのみを取得
        ProjectionExpression='user_status'
    )
    
    return {
        'statusCode': 200,
        'body': json.dumps(response['Items'])
    }
クエリ部分についてはAmazon DynamoDB > デベロッパーガイド記載の下記の部分を参考にしています。
リソースインターフェイスを使った同じクエリ操作を短くして簡略化できます。
import boto3
from boto3.dynamodb.conditions import Key, Attr
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('YourTableName')
response = table.query(
KeyConditionExpression=Key('pk').eq('id#1') & Key('sk').begins_with('cart#'),
FilterExpression=Attr('name').eq('SomeName')
)
引用:デベロッパーガイド
属性が値と等しいことを確認するために boto3.dynamodb.conditions.Key を使用しています。今回使用したのは等価比較を行うための eq です。
4. LambdaからGSIへのクエリを実行
test eventを作成してLabmdaを実行してみます。実行するイベントの内容は次の通りです。
{
  "body": "{\"userId\": \"user1\", \"timestamp\": \"2024-11-07\"}"
}
GSIに保存している次の項目の user_status を取得する想定です。
id (文字列):1
timestamp:2024-11-07
user_status:active
userId:user1
Lambdaを実行すると200で正常に下記のレスポンスを取得できました。
想定通り userId:user1 の user_status:active のデータを取得できていることが確認できます。
{
  "statusCode": 200,
  "body": "[{\"user_status\": \"active\"}]"
}
参考



