ステップ 4: データをクエリおよびスキャンする - Amazon DynamoDB

ステップ 4: データをクエリおよびスキャンする

query メソッドを使用して、テーブルからデータを取得できます。パーティションキーの値を指定する必要があります。ソートキーはオプションです。

Movies テーブルのプライマリキーは、以下の内容で構成されます。

  • year – パーティションキー。属性タイプは number です。 

  • title – ソートキー。属性タイプは string です。

1 年間にリリースされたすべての映画を検索するには、year のみ指定する必要があります。title を指定して、いくつかの条件 (ソートキー上) に基づいて映画のサブセットを取得することもできます。たとえば、2014 年にリリースされて、主題が「A」で始まる映画を探すことができます。

query メソッドに加えて、scan メソッドを使用して、テーブルデータをすべて取得することができます。

データのクエリとスキャンの詳細については、「DynamoDB でのクエリの操作」と「DynamoDB でのスキャンの使用」をそれぞれ参照してください。

ステップ 4.1: クエリ - 1 年間にリリースされたすべての映画

このステップに含まれているプログラムは、year 1985 にリリースされたすべての映画を取得します。

  1. 次のプログラムを MoviesQuery01.py というファイルにコピーアンドペーストします。

    import boto3 from boto3.dynamodb.conditions import Key def query_movies(year, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') response = table.query( KeyConditionExpression=Key('year').eq(year) ) return response['Items'] if __name__ == '__main__': query_year = 1985 print(f"Movies from {query_year}") movies = query_movies(query_year) for movie in movies: print(movie['year'], ":", movie['title'])
    注記

    ConditionExpression からインポートされた Key 関数と Attr 関数を使用すると、Boto 3 SDK により boto3.dynamodb.conditions が自動的に作成されます。また、文字列として ConditionExpression を指定することもできます。

    Amazon DynamoDB の使用可能な条件のリストについては、AWS SDK for Python (Boto 3) の使用開始の「DynamoDB の条件」を参照してください。

    詳細については、「条件式」を参照してください。

  2. このプログラムを実行するには、次のコマンドを入力します。

    python MoviesQuery01.py

注記

前のプログラムは、プライマリキーの属性によってテーブルをクエリする方法を示しています。DynamoDB では、必要に応じて 1 つ以上のセカンダリインデックスをテーブルに作成し、テーブルをクエリするのと同じ方法でそれらのインデックスをクエリできます。セカンダリインデックスは非キー属性のクエリを可能にすることで、アプリケーションに追加の柔軟性を提供します。詳細については、「セカンダリインデックスを使用したデータアクセス性の向上」を参照してください。

ステップ 4.2: クエリ - 1 年間にリリースされた特定のタイトルを持つすべての映画

このステップに含まれているプログラムは、year 1992 にリリースされたすべての映画のうち、title が「A」~「L」で始まる映画を取得します。

  1. 次のプログラムを MoviesQuery02.py というファイルにコピーアンドペーストします。

    from pprint import pprint import boto3 from boto3.dynamodb.conditions import Key def query_and_project_movies(year, title_range, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') print(f"Get year, title, genres, and lead actor") # Expression attribute names can only reference items in the projection expression. response = table.query( ProjectionExpression="#yr, title, info.genres, info.actors[0]", ExpressionAttributeNames={"#yr": "year"}, KeyConditionExpression= Key('year').eq(year) & Key('title').between(title_range[0], title_range[1]) ) return response['Items'] if __name__ == '__main__': query_year = 1992 query_range = ('A', 'L') print(f"Get movies from {query_year} with titles from " f"{query_range[0]} to {query_range[1]}") movies = query_and_project_movies(query_year, query_range) for movie in movies: print(f"\n{movie['year']} : {movie['title']}") pprint(movie['info'])
  2. このプログラムを実行するには、次のコマンドを入力します。

    python MoviesQuery02.py

ステップ 4.3: スキャン

scan メソッドは、テーブル全体のすべての項目を読み込み、テーブルの全データを返します。オプションで filter_expression を提供して、条件に一致する項目だけが返されるように指定できます。ただし、テーブル全体がスキャンされた後にのみ、フィルタが適用されます。

次のプログラムは、約 5,000 項目を含む Movies テーブル全体をスキャンします。スキャンは、1950 年代の映画のみ (約 100 項目) を取得して、残りはすべて破棄するようオプションのフィルタを指定します。

  1. 次のプログラムを MoviesScan.py というファイルにコピーアンドペーストします。

    from pprint import pprint import boto3 from boto3.dynamodb.conditions import Key def scan_movies(year_range, display_movies, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') scan_kwargs = { 'FilterExpression': Key('year').between(*year_range), 'ProjectionExpression': "#yr, title, info.rating", 'ExpressionAttributeNames': {"#yr": "year"} } done = False start_key = None while not done: if start_key: scan_kwargs['ExclusiveStartKey'] = start_key response = table.scan(**scan_kwargs) display_movies(response.get('Items', [])) start_key = response.get('LastEvaluatedKey', None) done = start_key is None if __name__ == '__main__': def print_movies(movies): for movie in movies: print(f"\n{movie['year']} : {movie['title']}") pprint(movie['info']) query_range = (1950, 1959) print(f"Scanning for movies released from {query_range[0]} to {query_range[1]}...") scan_movies(query_range, print_movies)

    このコードでは、以下の点に注意してください。

    • ProjectionExpression は、スキャン結果に必要な属性を指定します。

    • FilterExpression は、条件を満たした項目だけが返されるような条件を指定します。他のすべての項目は破棄されます。

    • scan メソッドは、ページという項目のサブセットを毎回返します。次に、応答の LastEvaluatedKey 値が、scan パラメーター経由で ExclusiveStartKey メソッドに渡されます。最後のページが返されると、LastEvaluatedKey は応答の一部ではなくなります。

    注記
    • ExpressionAttributeNames は、名前を置換します。year は DynamoDB の予約語であるため、これが使用されます。KeyConditionExpression を含むどの式でも直接使用することはできません。これに対処するため、式の属性名 #yr を使用できます。

    • ExpressionAttributeValues は、値を置換します。KeyConditionExpression を含むどの式にもリテラルを使用できないため、これを使用します。これに対処するため、式の属性値 :yyyy を使用できます。

  2. このプログラムを実行するには、次のコマンドを入力します。

    python MoviesScan.py

注記

テーブルで作成した任意のセカンダリインデックスで Scan メソッドを使用することもできます。詳細については、「セカンダリインデックスを使用したデータアクセス性の向上」を参照してください。