ステップ 3: Python で項目を作成、読み込み、更新、削除する - Amazon DynamoDB

ステップ 3: Python で項目を作成、読み込み、更新、削除する

このステップでは、Movies テーブルの項目で読み取り/書き込みオペレーションを実行します。

データの読み書きに関する詳細については、「項目と属性を操作する」を参照してください。

ステップ 3.1: 新しい項目を作成する

このステップでは、Movies テーブルに新しい項目を追加します。

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

    from pprint import pprint import boto3 def put_movie(title, year, plot, rating, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') response = table.put_item( Item={ 'year': year, 'title': title, 'info': { 'plot': plot, 'rating': rating } } ) return response if __name__ == '__main__': movie_resp = put_movie("The Big New Movie", 2015, "Nothing happens at all.", 0) print("Put movie succeeded:") pprint(movie_resp, sort_dicts=False)
    注記
    • プライマリキーは必須です。このコードは、プライマリキー (yeartitle) と info 属性を持つ項目を追加します。info 属性には、映画についての詳細情報を示すサンプル JSON が保存されます。

    • DecimalEncoder クラスは、Decimal クラスを使用して保存された数値を出力するために使用されます。Boto SDK は、Decimal クラスを使用して Amazon DynamoDB の数値を保持します。

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

    python MoviesItemOps01.py

ステップ 3.2: 項目を読み取る

前のプログラムでは、テーブルに次の項目を追加しました。

{ year: 2015, title: "The Big New Movie", info: { plot: "Nothing happens at all.", rating: 0 } }

get_item テーブルから項目を読み取る、Movies メソッドを使用できます。Moviesyear がわかれば、title から項目を読み込むことができるように、プライマリキー値を指定する必要があります。

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

    from pprint import pprint import boto3 from botocore.exceptions import ClientError def get_movie(title, year, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') try: response = table.get_item(Key={'year': year, 'title': title}) except ClientError as e: print(e.response['Error']['Message']) else: return response['Item'] if __name__ == '__main__': movie = get_movie("The Big New Movie", 2015,) if movie: print("Get movie succeeded:") pprint(movie, sort_dicts=False)
  2. このプログラムを実行するには、次のコマンドを入力します。

    python MoviesItemOps02.py

ステップ 3.3: 項目を更新する

update_item メソッドを使用して既存の項目を変更できます。既存の属性の値の更新、新しい属性の追加、または属性の削除を行えます。

このチュートリアルでは、次の更新を行います。

  • 既存の属性の値を変更します (ratingplot)。

  • 新しいリスト属性 (actors) を既存の info マップに追加します。

既存項目を以下に示します。

{ year: 2015, title: "The Big New Movie", info: { plot: "Nothing happens at all.", rating: 0 } }

この項目は次のように更新されます。

{ year: 2015, title: "The Big New Movie", info: { plot: "Everything happens all at once.", rating: 5.5, actors: ["Larry", "Moe", "Curly"] } }
  1. 次のプログラムを MoviesItemOps03.py というファイルにコピーアンドペーストします。

    from decimal import Decimal from pprint import pprint import boto3 def update_movie(title, year, rating, plot, actors, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') response = table.update_item( Key={ 'year': year, 'title': title }, UpdateExpression="set info.rating=:r, info.plot=:p, info.actors=:a", ExpressionAttributeValues={ ':r': Decimal(rating), ':p': plot, ':a': actors }, ReturnValues="UPDATED_NEW" ) return response if __name__ == '__main__': update_response = update_movie( "The Big New Movie", 2015, 5.5, "Everything happens all at once.", ["Larry", "Moe", "Curly"]) print("Update movie succeeded:") pprint(update_response, sort_dicts=False)
    注記

    このプログラムでは、UpdateExpression を使用して、指定された項目で実行するすべての更新を記述します。

    ReturnValues パラメーターは、DynamoDB に更新された属性 (UPDATED_NEW) のみを返すように指示します。

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

    python MoviesItemOps03.py

ステップ 3.4: アトミックカウンターを増分する

DynamoDB では、アトミックカウンターがサポートされています。そのため、update_item メソッドを使用して、他の書き込みリクエストを妨げることなく既存の属性値をインクリメントまたはデクリメントできます。(すべての書き込みリクエストは、受信された順に適用されます。)

次のプログラムは、映画の rating を増分する方法を示しています。実行するたびに、プログラムはこの属性を 1 つ増分します。

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

    from decimal import Decimal from pprint import pprint import boto3 def increase_rating(title, year, rating_increase, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') response = table.update_item( Key={ 'year': year, 'title': title }, UpdateExpression="set info.rating = info.rating + :val", ExpressionAttributeValues={ ':val': Decimal(rating_increase) }, ReturnValues="UPDATED_NEW" ) return response if __name__ == '__main__': update_response = increase_rating("The Big New Movie", 2015, 1) print("Update movie succeeded:") pprint(update_response, sort_dicts=False)
  2. このプログラムを実行するには、次のコマンドを入力します。

    python MoviesItemOps04.py

ステップ 3.5: 項目を更新する (条件付き)

次のプログラムは、条件とともに UpdateItem を使用する方法を示しています。条件が true と評価された場合、更新は成功します。それ以外の場合、更新は行われません。

この場合、項目は役者が 4 人以上いる場合にのみ更新されます。

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

    from pprint import pprint import boto3 from botocore.exceptions import ClientError def remove_actors(title, year, actor_count, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') try: response = table.update_item( Key={ 'year': year, 'title': title }, UpdateExpression="remove info.actors[0]", ConditionExpression="size(info.actors) > :num", ExpressionAttributeValues={':num': actor_count}, ReturnValues="UPDATED_NEW" ) except ClientError as e: if e.response['Error']['Code'] == "ConditionalCheckFailedException": print(e.response['Error']['Message']) else: raise else: return response if __name__ == '__main__': print("Attempting conditional update (expecting failure)...") update_response = remove_actors("The Big New Movie", 2015, 3) if update_response: print("Update movie succeeded:") pprint(update_response, sort_dicts=False)
  2. このプログラムを実行するには、次のコマンドを入力します。

    python MoviesItemOps05.py

    プログラムは次のメッセージでエラーになります。

    条件付きリクエストが失敗しました

    このプログラムがエラーになるのは、映画に 3 人の役者が出演しているが、条件は役者が 3 人より多いことをチェックしているためです。

  3. ConditionExpression が次のようになるようにプログラムを変更します。

    ConditionExpression="size(info.actors) >= :num",

    条件が、3 より大きいではなく 3 以上になりました。

  4. プログラムを再度実行します。これで、UpdateItem オペレーションが成功します。

ステップ 3.6: 項目を削除する

プライマリキーを指定することで、delete_item メソッドを使用して 1 つの項目を削除できます。オプションで ConditionExpression を指定して、条件を満たさない場合に項目の削除を防ぐことができます。

次の例では、レーティングが 5 以下の特定の映画項目を削除しようとします。

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

    from decimal import Decimal from pprint import pprint import boto3 from botocore.exceptions import ClientError def delete_underrated_movie(title, year, rating, dynamodb=None): if not dynamodb: dynamodb = boto3.resource('dynamodb', endpoint_url="http://localhost:8000") table = dynamodb.Table('Movies') try: response = table.delete_item( Key={ 'year': year, 'title': title }, ConditionExpression="info.rating <= :val", ExpressionAttributeValues={ ":val": Decimal(rating) } ) except ClientError as e: if e.response['Error']['Code'] == "ConditionalCheckFailedException": print(e.response['Error']['Message']) else: raise else: return response if __name__ == '__main__': print("Attempting a conditional delete...") delete_response = delete_underrated_movie("The Big New Movie", 2015, 5) if delete_response: print("Delete movie succeeded:") pprint(delete_response, sort_dicts=False)
  2. このプログラムを実行するには、次のコマンドを入力します。

    python MoviesItemOps06.py

    プログラムは次のメッセージでエラーになります。

    条件付きリクエストが失敗しました

    このプログラムは、この特定の映画のレーティングが 5 より大きいため、実行できません。

  3. table.delete_item で条件を削除するようにプログラムを変更します。

    response = table.delete_item( Key={ 'year': year, 'title': title } )
  4. プログラムを実行します。ここでは、条件を削除したため、削除が成功します。