9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DynamoDBで条件に一致するレコードをまとめて削除する。

Last updated at Posted at 2020-06-03

GUIでは一覧表示から全件チェックして削除できるが1度に実施するコマンドはない。
おそらくget-itemし表示しているデータを片っ端からdelete-itemしているのではなかろうか。
前方一致したレコードを全て削除する機会があり手でぽちぽちするのも面倒なので調べてみた。

そもそものputとdelete(CLI)

put-item

  • 数字もクオーテーションでくくる。
  • jsonも入れられる。ただ、クオートをエスケープする必要はある。
$ aws dynamodb put-item --table-name test --item '{"part":{"S":"hoge"}, "num":{"N":"1"}, "obj":{"S":"{\"test\": \"aaa\"}"}}'
  • 同じパーティションキーで叩くとエラーはしないで勝手に上書きされる。
  • そもそもレスポンスは何もない。
  • 返値が欲しいときはオプションで色々指定できる。
$ aws dynamodb put-item --table-name test --item '{"part":{"S":"hoge2"}, "num":{"N":"2"}, "obj":{"S":"{\"test\": \"aaa\"}"}}' --return-consumed-capacity TOTAL
{
    "ConsumedCapacity": {
        "TableName": "test",
        "CapacityUnits": 1.0
    }
}

delete-item

  • --keyは必須。~~削除対象に該当するキーを一つ書いておけばいい?~~削除対象を指定
  • --keyがそもそも条件に当てはまっていないとエラーする → あとからわかったが当然
  • このコマンドの条件は期待した条件に一致するものを全て削除するものではない。
  • --expression-attribute-valuesではファイルを指定しても直接書いてもいい
  • --condition-expressionにダイレクトに書くと怒られる
  • 条件にbegins_withなどを指定する場合これらは関数としての記法を取る
    https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html
OK
$ aws dynamodb delete-item --table-name test --key '{"part":{"S":"hoge"}}' --condition-expression "part = :part" --expression-attribute-values file://values.json

$ aws dynamodb delete-item --table-name test --key '{"part":{"S":"hoge"}}' --condition-expression "part = :part" --expression-attribute-values '{":part": {"S": "hoge"}}'

$ aws dynamodb delete-item --table-name test --key '{"part":{"S":"hoge"}}' --condition-expression "begins_with (part, :part)" --expression-attribute-values '{":part": {"S": "hoge"}}'
./values.json
{
    ":part": {"S": "hoge"}
}
NG
$ aws dynamodb delete-item --table-name test --key '{"part":{"S":"hoge"}}' --condition-expression "part = '{\"S\": \"hoge\"}'"
An error occurred (ValidationException) when calling the DeleteItem operation: Invalid ConditionExpression: Syntax error; token: "'", near: "= '{"

$ aws dynamodb delete-item --table-name test --key '{"part":{"S":"fuga"}}' --condition-expression "part = :part" --expression-attribute-values '{":part": {"S": "hoge"}}'
An error occurred (ConditionalCheckFailedException) when calling the DeleteItem operation: The conditional request failed

→ やりたいことはできないらしいので自分で組む必要があるっぽい。

条件に合致するデータを全件削除(boto3+lambda)

この記事を参考

import json
import boto3
from boto3.dynamodb.conditions import Key, Attr

TABLENAME='test'
dynamodb = boto3.client('dynamodb')

# 条件に一致するレコードを全て取得
def getRecords(flt, val):
    records = []
    ExclusiveStartKey = None
    while True:
        if ExclusiveStartKey == None:
            response = dynamodb.scan(
                TableName=TABLENAME, 
                FilterExpression=flt,
                ExpressionAttributeValues=val,
                Limit=2 # テストとして上限を超えるケースを起こしてみるため2を設定
                )
        else:
            response = dynamodb.scan(
                TableName=TABLENAME, 
                FilterExpression=flt,
                ExpressionAttributeValues=val,
                Limit=2, # テストとして上限を超えるケースを起こしてみるため2を設定
                ExclusiveStartKey=ExclusiveStartKey
                )
        for res in response["Items"]:
            records.append(res)
        if "LastEvaluatedKey" in response:
            ExclusiveStartKey = response["LastEvaluatedKey"]
        else:
            break
    return records

# 指定条件のレコードを削除    
def deleteRecords(flt):
    dynamodb.delete_item(
        TableName=TABLENAME,
        Key=flt
        )
    return 0 # エラーハンドリングしたい

def lambda_handler(event, context):
    targets = getRecords(
        'begins_with(part, :part)',
        {":part": {"S": "hoge"}}, # eventでパラメータを受け取るなどしたら汎用性上がりそう
        )
    print("get records")
    print(targets)
    
    for target in targets:
        print(target["part"]["S"])
        res = deleteRecords(
            {'part': target["part"]}
            )
    
    return 0

ただ、この方法では削除1回1回にリクエストが発生するので一括してできる方法を検討したい。
なおbegins_withはqueryでは指定できなそうなのでscanを使用した。

import json
import boto3
from boto3.dynamodb.conditions import Key, Attr

d = boto3.resource('dynamodb')
table = d.Table('test')
def lambda_handler(event, context):
    g = []
    ExclusiveStartKey = None
    while True:
        if ExclusiveStartKey == None:
            response = table.query(
                KeyConditionExpression=Key("part").begins_with("hoge"),
                Limit=2
            )
        else:
            response =  table.query(KeyConditionExpression="part",Limit=2, ExclusiveStartKey=ExclusiveStartKey)
        g.extend(response["Items"])
        if ("LastEvaluatedKey" in response) == True:
            ExclusiveStartKey = response["LastEvaluatedKey"]
        else:
            break
    print(g)

"errorMessage": "An error occurred (ValidationException) when calling the Query operation: Query key condition not supported"

参考

9
4
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
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?