LoginSignup
0
0

python boto3でDynamoDBを操作する場合の自分向けチートシート

Posted at

概要

毎回boto3でDynamoDBを操作する場合の書き方を忘れるので、自分用のチートシートを作成します。

想定するテーブル

本ページで扱うテーブル情報は以下とします。
学校の科目ごとの成績を管理するテーブルです。

項目 内容 備考
テーブル名 school_score_table
パーティションキー(PK) student 生徒ごとにユニークな名称
ソートキー(SK) subject 科目はMath, English, Scienceなど
グローバル セカンダリ インデックス(GSI) subject-Index 科目だけでクエリするためのインデックス

入れておくレコードはこんな想定です。

[
    {
        'student': 'Alice',
        'subject': 'Math',
        'grade': 'A'
    },
    {
        'student': 'Alice',
        'subject': 'English',
        'grade': 'B'
    },
    {
        'student': 'Bob',
        'subject': 'Math',
        'grade': 'C'
    },
    {
        'student': 'Bob',
        'subject': 'English',
        'grade': 'A'
    }
]

DynamoDBのテーブル設定

最初のテーブル設定部分です。
URLはパラメータストアやLambda環境変数から取ってくるのが良いです。
また、DynamoDBのテーブル操作が頻繁に行われるのであれば、テーブル名を変数や引数としたクラス化や関数化してあげるとスマートな気がします。

import boto3
from boto3.dynamodb.conditions import Key

URL = 'http://dynamodb.ap-northeast-1.amazonaws.com/xxxxxxxxxxxx/'
TABLE_NAME = 'school_score_table'

dynamodb = boto3.resource('dynamodb', endpoint_url=URL)
table = dynamodb.Table(TABLE_NAME)

テーブル操作

get_item

get_item()は、テーブルから1つのレコードを取得します。
1つのレコードのため、応答は辞書型となります。

get_item()はレコードが一意に決まるKeyを設定します。
今回はPKとSKでレコードが一意に決まるため、PKとSKを指定しています。
SKがない場合(PKだけで一意)の場合には、SKを指定する必要はありません。

response = table.get_item(
    Key={
        'student': 'Alice',
        'subject': 'English'
    }
)
print(response['Item'])
# {'student': 'Alice', 'subject': 'English', 'grade': 'B'}

query_item

query()は、テーブルから条件に一致するレコードをKeyConditionExpressionで指定してリストで取得します。
クエリの仕方はいくつかバリエーションがあります。

PKだけでクエリする

response = table.query(
    KeyConditionExpression=Key('student').eq('Alice')
)

print(response['Items'])
# [{'student': 'Alice', 'subject': 'Math', 'grade': 'A'}, {'student': 'Alice', 'subject': 'English', 'grade': 'B'}]

GSIでクエリする

response = table.query(
    IndexName='subject-Index',
    KeyConditionExpression=Key('subject').eq('Math')
)

print(response['Items'])
# [{'student': 'Alice', 'subject': 'Math', 'grade': 'A'}, {'student': 'Bob', 'subject': 'Math', 'grade': 'C'}]

query()では、FilterExpressionを使ってクエリ結果の絞り込みができます。ただし、FilterExpressionの有無にかかわらず、使用されるRead Capacity Unit(読取容量)は変化しません。

put_item

put_item()は、テーブルに1つのレコードを追加します。
既に同じ主キーを持つレコードがある場合は、古いアイテムを書き換えます。

table.put_item(
    Item={
        'student': 'Charly',
        'subject': 'Math',
        'grade': 'B'
    }
)

新しい項目が既存の項目を置き換えるのを防ぐには、attribute_not_exists関数と、PKの属性名を含む条件式を使用します。

以下はstudentがない場合のみ、レコードを追加する処理の例です。

table.put_item(
    Item=item,
    ConditionExpression='attribute_not_exists(student)'
)

update_item

update_item()は、指定したレコードを更新します。
指定したキーがない場合は、レコードを新たに追加します。

table.update_item(
    Key={
        'student': 'Alice',
        'subject': 'Math'
    },
    UpdateExpression='SET grade = A+', # string型のプロパティはUpdateExpressionのみでOK
)

String型以外のプロパティの更新方法

UpdateExpressionは、string型のみ使用できます。
number型のプロパティを更新したい場合は、ExpressionAttributeValuesを使います。

table.update_item(
    Key={
        'student': 'Alice',
        'subject': 'Math'
    },
    UpdateExpression='SET score = :val', # :valという変数を定義
    ExpressionAttributeValues={
        ':val': 90 # 変数に入れる値を設定する
    }
)

また、ExpressionAttributeNamesを指定することで、UpdateExpressionのプロパティ名を変数として定義できます。

table.update_item(
    Key={
            'student': 'Alice',
            'subject': 'Math'
    },
    UpdateExpression='SET #key_name1 = :val1, #key_name2 = :val2',
    ExpressionAttributeNames={
        '#key_name1': 'score',
        '#key_name2': 'grade',
    },
    ExpressionAttributeValues={
        ':val1': '90',
        ':val2': 'A+'
    }
)

更新する条件を指定する

ConditionExpressionを使うと、更新する条件を指定できます。
以下はscoreの現在値が更新値よりも大きい場合のみ更新します。

table.update_item(
    Key={
            'student': 'Alice',
            'subject': 'Math'
        },
    ConditionExpression='#key_name1 > :val1',
    UpdateExpression='SET #key_name1 = :val1, #key_name2 = :val2',
    ExpressionAttributeNames={
        '#key_name1': 'score',
        '#key_name2': 'grade',
    },
    ExpressionAttributeValues={
        ':val1': '90',
        ':val2': 'A+'
    }
)

また、ConditionExpressionを満たさない場合、ConditionalCheckFailedExceptionにより書込みが失敗します。

delete_item

delete_item()は、テーブルのレコードを1つ削除します。
指定の仕方はget_item()と同じようにKeyを使います。

table.delete_table(
    Key={
        'student': 'Alice',
        'subject': 'English'
    }
)

まとめ

自分の習熟度に応じて、随時更新していきたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0