DynamoDBの query() で FilterExpression を使ってデータ取得条件を設定する
何らかの情報取得APIを作るとき、権限チェックをします。たとえば、「Aさんが所持しているデバイスか?」といった具合です。他人のデバイスの情報取得をしている場合、それは403エラー等で失敗させる必要があります。
このような実装を考えてみました。
おすすめの方
- DynamoDBの
get_item()
を参考にしたい方 - DynamoDBの
query()
を参考にしたい方
実験用のDynamoDBテーブルを用意する
適当なDynamoDBテーブルを作成します。
サンプルデータを用意します。
{ "userId": "test1", "devices": [ "d0001", "d0002" ] }
例1: ソースコードで判定する
DynamoDBテーブルから「指定したユーザが所持するデバイス一覧」を取得し、判定する例です。 指定デバイスを所持しているか?の判定をif文で行っています。
import boto3 from boto3.dynamodb.conditions import Key, Attr dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('user-table') options = { 'Key': { 'userId': 'test1', }, 'ProjectionExpression': '#devices', 'ExpressionAttributeNames': { '#devices': 'devices' } } res = table.get_item(**options) if 'd0001' in res['Item']['devices']: print('ok') else: print('ng')
例2: FilterExpression を活用する
DynamoDBテーブルから「指定したユーザが指定したデバイスを所持する件数」を取得し、判定する例です。 指定デバイスを所持しているか?の判定はDynamoDB側に任せています。
import boto3 from boto3.dynamodb.conditions import Key, Attr dynamodb = boto3.resource('dynamodb') table = dynamodb.Table('user-table') options = { 'Select': 'COUNT', 'KeyConditionExpression': Key('userId').eq('test1'), 'FilterExpression': Attr('devices').contains('d0001'), } res = table.query(**options) if res['Count'] != 0: print('ok') else: print('ng')
おまけ
DynamoDBで使える条件式は下記が参考になります。
- DynamoDB customization reference — Boto3 Docs 1.16.50 documentation
- 比較演算子および関数リファレンス - Amazon DynamoDB
よく使うのは下記だと思います(個人の感想)。
- between
- eq
- ne
- contains
また、FilterExpression
は、&
と|
で複合条件ができます。
options = { 'KeyConditionExpression': Key('userId').eq('test1'), 'FilterExpression': Attr('devices').contains('d0001') & Attr('aaa').eq('bbb') | Attr('xxx').ne('yyy'), } res = table.query(**options)
さいごに
本記事ではかなりシンプルな例でしたが、FilterExpression
では様々な条件の組み合わせも可能です。ぜひ活用してみてください。