DynamoDBのscan()で「Falseの場合のみ取得」をしたらデータHitしなかった話
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度でもハマれば覚えると思います。どなたかの参考になれば幸いです。