
DynamoDBのscan()で「Falseの場合のみ取得」をしたらデータHitしなかった話
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
DynamoDBテーブルのデータをscan()やquery()で検索するとき、FilterExpressionを使って指定した条件を満たしたデータのみ取得することがよくあります。
しかし、DynamoDBテーブルのデータ内容によっては条件一致しないことがありました。
DynamoDBのscan()で「Falseの場合」にデータHitしなかった
DynamoDBテーブルの様子
DynamoDBテーブルにToDoリストのデータがあるとします。
doneがtrue: 完了doneが無い: 未完了
未完了のデータを取得すると、0件になる
次のようにDynamoDBテーブルから「未完了のデータ一覧」を取得します。 このとき、「doneがFalseならHit」させようとしていますが、取得したデータは0件になったのです。
import boto3
from boto3.dynamodb.conditions import Attr, Key
dynamodb = boto3.resource('dynamodb')
def main():
table = dynamodb.Table('todo-table')
option = {
'FilterExpression': Attr('done').eq(False)
}
resp = table.scan(**option)
for item in resp.get('Items'):
print(item)
if __name__ == "__main__":
main()
「doneがFalseなら」がHitしない理由
done項目の有無が原因でした。下記のFilterExpressionは、「doneの項目がfalseなら」となりますが、そもそもdone自体が存在しないので、この条件は偽になるのです。……そりゃそうだ。
option = {
'FilterExpression': Attr('done').eq(False)
}
未完了のデータを取得する方法
2つの方法があります。
doneにfalseを設定する- FilterExpressionの条件を「
doneがTrue以外なら」にする
その1. doneにfalseを設定する
DynamoDBテーブルのデータについて、あらかじめdoneにfalseを入れておきます。
このようにすれば、「doneの項目がfalseなら」でHitします。
option = {
'FilterExpression': Attr('done').eq(False)
}
その2. FilterExpressionの条件を「doneがTrue以外なら」にする
DynamoDBテーブルのデータを変更せず検索したい場合は、FilterExpressionの条件を「doneの項目がtrue以外なら」に変更すればHitします。trueではないですからね。そりゃそうだ。
option = {
'FilterExpression': Attr('done').ne(True)
}
さいごに
地味なポイントですが、1度でもハマれば覚えると思います。どなたかの参考になれば幸いです。








