Python(boto3)での DynamoDB GetItem

get_item完全なプライマリキー で 1 件のアイテムを取得します。boto3 の 低レベルクライアントboto3.client("dynamodb"))は双方向で DynamoDB JSON を話すので、キーは型で包んで渡し、アイテムも同じ形で返ってきます。queryscan との違いはアイテム単位の操作で扱っています。

コード

import boto3

client = boto3.client("dynamodb")

response = client.get_item(
    TableName="Music",
    Key={"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}},
    ProjectionExpression="#proj0, #proj1, #proj2, #proj3",
    ExpressionAttributeNames={"#proj0": "Artist", "#proj1": "SongTitle", "#proj2": "AlbumTitle", "#proj3": "Year"},
)

item = response.get("Item")
if item is None:
    print("Item not found")
else:
    print(item)

解説

ヒットしなかった場合、レスポンスには Item キーがそもそも含まれませんNone でもなければ、空の dict でもありません。同じテーブルを、存在しないキーで読んだときのレスポンスのトップレベルキーは、ちょうどこれだけでした。

['ResponseMetadata']

だからこのスニペットは response.get("Item") を使っています。response["Item"] は、ごく普通の「見つからない」経路で KeyError を送出します。これが、行が 1 つ無いだけで Web ハンドラーが 500 になる仕組みです。それでも読み取り分は課金されます。AWS の読み取りキャパシティのページには、"if you perform a read operation on an item that doesn't exist, DynamoDB will still consume read throughput as outlined above" と書かれています(2026-07-28 取得)。

Year は予約語です。生成されたスニペットが射影する属性すべてに別名を付けているのはそのためです#proj の別名を外して ProjectionExpression="Year" を渡すと、エンジンは読み取りを拒否します。

ValidationException: Invalid ProjectionExpression: Attribute name is a reserved keyword; reserved keyword: Year

無条件に別名を付けてもコストはゼロで、この種の失敗をまるごと取り除けます。リストの総数は 573 語です。"Attribute name is a reserved keyword"を参照してください。

Key を間違える 4 通りと、3 種類のメッセージ。どれも、人が予想する "provided key element does not match the schema" エラーではないので、見分けておく価値があります。Artist(パーティション)+ SongTitle(ソート)をキーとする Music テーブルに対して再現しました。

渡したものValidationException メッセージ(逐語)
{"Artist": …} — ソートキーが無いThe number of conditions on the keys is invalid
{"Artist": …, "SongTitle": …, "Extra": …}The number of conditions on the keys is invalid
{"Artist": …, "Song": …} — 属性名が違うOne of the required keys was not given a value
{"Artist": {"N": "1"}, …} — 型が違うOne or more parameter values were invalid: Type mismatch for key

キー属性が 足りない 場合と 余分な 場合が同じメッセージになる点に注目してください。つまり「conditions の数」が意味しているのは「渡された数が少なすぎる」ではなく「キースキーマちょうどを渡さなかった」ということです。

ProjectionExpression が削るのはペイロードであって、請求ではありません。約 15 KB のアイテムを ReturnConsumedCapacity="TOTAL" 付きで 3 通りに読んだ結果です。

full item, eventually consistent          CapacityUnits: 2.0
ProjectionExpression="#y" (Year only)     CapacityUnits: 2.0
ProjectionExpression="#y" + ConsistentRead  CapacityUnits: 4.0

射影はレスポンスを約 15 KB から数値ひとつに変えましたが、コストは何も変えませんでした。AWS ははっきりこう述べています。"The number of capacity units consumed will be the same whether you request all of the attributes (the default behavior) or just some of them (using a projection expression)"(Query API Reference、2026-07-28 取得)。そのリストの中で数値を動かす唯一のフラグが ConsistentRead=True で、これは 2 倍にします。射影が本来何のためのものかは射影式を参照してください。

リソース API は書き方がきれいになったものではなく、別の契約ですboto3.resource("dynamodb").Table("Music").get_item(...) は素の Python を返し、数値はすべて decimal.Decimal になります。

{'Artist': 'Arturo Sandoval', 'AlbumTitle': 'Danzon', 'Awards': Decimal('0'), 'Year': Decimal('1994'), 'SongTitle': 'Cubano Chant'}

これは諸刃の剣です。同じ API を通して float で書き戻すと、リクエストがマシンを出る前に例外が上がります。

TypeError: Float types are not supported. Use Decimal types instead.

これに刺さったら、"Float types are not supported"に対処法があります。本当の罠は、1 つのコードベースで 2 つの API を混ぜることです。低レベルクライアントは、リソース API なら拒否したはずの {"N": "1.5"} を平気で受け取ります。

エラーは botocore の例外として届き、boto3 はそれらに実クラスを与えています。1.43.58 では、条件が満たされなかったときに送出されるオブジェクトは ClientError のサブクラスである ConditionalCheckFailedException なので、except ClientErrorerr.response["Error"]["Code"] のチェックを添える方法も、except client.exceptions.ConditionalCheckFailedException も、どちらも機能します。コードベースで既に使っているほうを選んでください。str(e) でのマッチはやめましょう。

ビジュアルに行う

手作業で別名を付ける前に。無料の DynamoDB 予約語チェッカーは、属性名を渡すと 573 の予約語のどれに当たっているかを教え、そのまま貼り付けられる ExpressionAttributeNames のマップを出力します。

テーブルを参照して自分のデータに対して GetItem を実行するには — キーのフォーム、結果グリッド、リクエストの boto3 としてのコピー — DynoTable をダウンロードしてください。

関連ガイド

参考資料

2026-07-28 に、DynamoDB Local(amazon/dynamodb-local)のポート 9000 に対し boto3 1.43.58 / botocore 1.43.58 で再現しました。上記のメッセージとキャパシティの数値はすべてエンジンの出力をそのまま逐語で写したものです。DynamoDB Local はサービス本体ではありません。両者で表現が異なると分かっているエラーについては、そのエラーページで明記しています。

Console なしで DynamoDB を扱う

DynamoDB では実行できない本物の SQL(JOINs、GROUP BY、集計)を実行する高速な DynamoDB デスクトップクライアント。ビジュアル編集と、あなた自身の Bedrock キーで動く AI エージェントを備えています。

30日間無料トライアル、クレジットカード不要 — その後は期限のない Free プラン。