DynamoDBからqueryでデータを取り出すPythonのプログラム | そう備忘録

DynamoDBからqueryでデータを取り出すPythonのプログラム

DynamoDB

今回は query を使ってデータを取り出すPythonのプログラムについて分かったことを記事にしておく。

以前のtablescanと使ったDynamoDBに関する記事は以下の通り。

事前準備

DynamoDBにアクセス用のアクセスキーIDの作成やPythonからDynamoDBにアクセスするために必要なモジュール(Boto3)のインストールについては以前の記事を参照

プログラム

実行環境

OS

Windows10 Pro及びHome 64Bit

Python

Ver3.7.7(Anaconda上で実行)

プログラムソースコード

queryを使ったプログラムは以下の通り。

# -*- coding: utf-8 -*-
"""
Created on Mon Jun 29 14:55:27 2020

@author: Souichirou.Kikuchi
"""

import json
from typing import List
from decimal import Decimal

import boto3
from boto3.resources.base import ServiceResource
from boto3.dynamodb.types import Binary
from boto3.dynamodb.conditions import Key, Attr # Query用

def scan_table(table_name: str, dynamodb: ServiceResource) -> List[dict]:
    table = dynamodb.Table(table_name) # DynamoDBテーブル読み込み
    resp = table.query(
        KeyConditionExpression=Key('tempkeyindex').eq('2020-07-10 21:24:01SKRPZ0002'),
        FilterExpression=Attr('min_temp').gte(5) 
        )
    table_items = resp['Items'] # 1回のTableScanで取得できる件数に限界があるので複数回に渡って取得する
    while 'LastEvaluatedKey' in resp: # 最後まで読み込み
        resp = table.query(
            KeyConditionExpression=Key('tempkeyindex').eq('2020-07-10 21:24:01SKRPZ0002'),
            FilterExpression=Attr('min_temp').gte(5), 
            ExclusiveStartKey=resp['LastEvaluatedKey']
        )
        table_items.extend(resp['Items'])
    return table_items

def default_proc(obj) -> object: # 型変換
    if isinstance(obj, Decimal): # Decimalであればintかfloatに変換
        if int(obj) == obj:
            return int(obj)
        else:
            return float(obj)
    elif isinstance(obj, Binary):
        return obj.value
    elif isinstance(obj, bytes):
        return obj.decode(encoding='default')
    elif isinstance(obj, set):
        return list(obj)
    try:
        return str(obj)
    except Exception:
        return None

def put_data(table_items: List[dict]) -> None:
    with open('./export.json', 'w') as f:
        json.dump(table_items, f, default=default_proc, ensure_ascii=False, sort_keys=True, indent=4)

if __name__ == '__main__':
    table_name = 'テーブル名'
    dynamodb = boto3.resource('dynamodb',
                          aws_access_key_id='アクセスキーID',
                          aws_secret_access_key='シークレットアクセスキー',
                          region_name='リージョン')
    table_items = scan_table(table_name, dynamodb)
    put_data(table_items)

補足説明

プライマリーキー

今回読み込んだテーブルには以下のキーを設定している。

  • tempkeyindex:プライマリーパーティションキー
  • clientid:プライマリーソートキー

KeyConditionExpression

KeyConditionExpressionではプライマリパーティションキー及びプライマリーソートキーを指定する。

プライマリパーティションキーはeq(イコール)のみ指定可能。

プライマリーソートキーを&(アンド条件)で指定する事も可能だがプライマリパーティションキーが指定されていることが条件でソートキーのみを指定することは出来ない。

尚、ソートキーの方はbetween、gte(大なりイコール)等の指定が可能。

        KeyConditionExpression=Key('tempkeyindex').eq('2020-07-10 21:24:01SKRPZ0002') & Key('clientid').between('SKRPZ0002','SKRPZ0003')

FilterExpression

FilterExpressionはプライマリパーティションキー、プライマリーソートキー以外の項目が指定できる。

しかしKeyConditionExpressionが指定されている事が前提でFilterExpressionのみを指定する事が出来なかった。

またFloat型の項目は指定出来ず、”DECIMAL型にして下さい”とのエラーメッセージが表示されてしまった。

  • eq:イコール
  • gt:大なり
  • gte:大なりイコール
  • contains:含む
  • lt:小なり
  • lte:小なりイコール

等が指定できる。

最後に

この記事が何処かで誰かの役に立つことを願っている。

尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。

souichirou

やった事を忘れない為の備忘録 同じような事をやりたい人の参考になればと思ってブログにしてます。 主にレゴ、AWS(Amazon Web Services)、WordPress、Deep Learning、RaspberryPiに関するブログを書いています。 仕事では工場に協働ロボットの導入や中小企業へのAI/IoT導入のアドバイザーをやっています。 2019年7月にJDLA(一般社団法人 日本デイープラーニング協会)Deep Learning for GENERALに合格しました。 質問は記事一番下にあるコメントかメニュー上部の問い合わせからお願いします。

おすすめ

質問やコメントや励ましの言葉などを残す

名前、メール、サイト欄は任意です。
またメールアドレスは公開されません。