この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
DynamoDBを使っていると、「特定の項目がxxx
のデータがある? ない?」と調べたくなる場合があります。
たくさんある全データをscan()
して判断するのは大変なので、今回は、GSIを使う方法を試してみました。
例えば、写真のメタデータを管理するDynamoDBテーブル
写真のメタデータを管理するDynamoDBテーブルを例とします。
photoId | s3Bucket | s3Key | place |
---|---|---|---|
p0001 | my-photo-bucket | foo/bar/aaa.jpg | Tokyo |
p0002 | my-photo-bucket | foo/bar/bbb.jpg | Iwate |
p0003 | my-photo-bucket | foo/bar/ccc.jpg | Osaka |
p0004 | my-photo-bucket | foo/bar/ddd.jpg | Tokyo |
p0005 | my-photo-bucket | foo/bar/eee.jpg | Fukuoka |
このとき、下記を調べたい例です。
place
がTokyo
のデータはある?ない?place
がAmerica
のデータはある?ない?
DynamoDBテーブルを準備する
CloudFormationテンプレート
place
でGSIを作成しています。有無を知りたいだけなので、GSIはKEYS_ONLY
を使います。
dynamodb.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: DynamoDB Sample
Resources:
DemoTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: photo-meta-table
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: photoId
AttributeType: S
- AttributeName: place
AttributeType: S
KeySchema:
- AttributeName: photoId
KeyType: HASH
GlobalSecondaryIndexes:
- IndexName: place-index
KeySchema:
- AttributeName: place
KeyType: HASH
Projection:
ProjectionType: KEYS_ONLY
デプロイ
aws cloudformation deploy \
--template-file dynamodb.yaml \
--stack-name DynamoDB-Photo-Meta-Sample-Stack \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
DynamoDBの特定項目の有無を調べる
サンプルコード
下記のPythonコードのように調べることができます。
app.py
import boto3
from boto3.dynamodb.conditions import Key
def main():
dybamodb = boto3.resource('dynamodb')
res = is_exist_place('Tokyo', dybamodb)
print(res)
def is_exist_place(place: str, dynamodb) -> bool:
table = dynamodb.Table('photo-meta-table')
options = {
'IndexName': 'place-index',
'Select': 'COUNT',
'KeyConditionExpression': Key('place').eq(place),
'Limit': 1,
}
res = table.query(**options)
if res.get('Count', 0) != 0:
return True
return False
if __name__ == '__main__':
main()
今回、調べたい項目(place
)をGSIのパーティションキーに設定しています。たとえば、GSIのパーティションキーにTokyo
を指定してquery()
を実行すれば、place==Tokyo
のデータのみを取得できます。そのため、「ある? ない?」を判断するためには、Limit=1
を指定すれば十分です。全検索をする必要が無いので、とてもシンプルです。
Tokyoが2つあるとき
Tokyo
が2つあるときに調べると、True
が得られます。
app.py
$ python app.py
True
Tokyoが1つあるとき
Tokyo
が1つあるときに調べると、True
が得られます。
app.py
$ python app.py
True
Tokyoが無いとき
Tokyo
がないときに調べると、False
が得られます。
app.py
$ python app.py
False
Tokyoがあって、placeが無い項目もある
True
が得られます。
app.py
$ python app.py
True
Tokyoが無くて、placeが無い項目もある
False
が得られます。
app.py
$ python app.py
False
さいごに
「1つでもxxx
があれば、AAAの処理をする」みたいな処理を作る必要があったので試してみました。
簡単にできて良かったです。