概要
Geo Library for Amazon DynamoDBとは?
AWS公式ブログのこの記事で解説されているJava用のライブラリ。リポジトリはこちら。
DynamoDBで緯度経度、半径で絞り込んでクエリできる。ただし、プライマリキーの構造はライブラリが規定する形になるので、既存のテーブルに対してクエリできるわけではなく、テーブル作り直しが必要になる。
dynamodb-geo.jsはそれを有志がJS用にポーティングしたもの。本記事ではこちらのJS版を使ってみた。
テーブルの構造
- プライマリキーはハッシュキー+レンジキーになる
- ハッシュキーの値はライブラリによって自動的に埋められる
- レンジキーの値は自分で決められる。このライブラリを使う場合、レンジキーだけでテーブル内でユニークにしなければいけないので、レンジキーに実質的なIDを入れることになる
-
geoHash
というカラムが作られ、6924445843714161599
のような値で埋められる- Geohashとは言ってもこのジオハッシュとは別物っぽい
-
geoJson
というカラムが作られ、{"type":"POINT","coordinates":[139.697004,35.755606]}
のような値で埋められる - ハッシュキー+geohashに対してインデックスが作られる
クエリ
矩形範囲を取ってくるqueryRectangle
と半径内を取ってくるqueryRadius
がある。
約1400件のアイテムを入れてqueryRadius
をやってみたところ、
- 1000メートル以内のアイテムを取ってくると約600msかかった
- 10000メートル以内のアイテムを取ってくると約1200msかかった
1000メートル以内のとき、下記のようなクエリが8回投げられて、
{ TableName: 'geoPorts_hash1',
KeyConditions:
{ hashKey:
{ ComparisonOperator: 'EQ', AttributeValueList: [ { N: '6' } ] },
geohash:
{ ComparisonOperator: 'BETWEEN',
AttributeValueList:
[ { N: '6917783255345266689' }, { N: '6917783289705005055' } ] } },
IndexName: 'geohash-index',
ConsistentRead: false,
ReturnConsumedCapacity: 'TOTAL',
ExclusiveStartKey: null }
消費キャパシティはこんな感じだった。
Count=19, ScannedCount=19, ConsumedCapacity=2
Count=4, ScannedCount=4, ConsumedCapacity=0.5
Count=1, ScannedCount=1, ConsumedCapacity=0.5
Count=3, ScannedCount=3, ConsumedCapacity=0.5
Count=2, ScannedCount=2, ConsumedCapacity=0.5
Count=2, ScannedCount=2, ConsumedCapacity=0.5
Count=4, ScannedCount=4, ConsumedCapacity=0.5
Count=2, ScannedCount=2, ConsumedCapacity=0.5
感想
意外とクエリが遅かった。
AWSの元リポジトリはアーカイブされているし、スター数も多くないので、イマイチなのかもしれない。
DynamoDB GeoLocation Lookup : aws - RedditでもDynamoDBをGeoLocationに使うのは間違いだと言われているのでそうなのかも。というかAWSサーバーレスアーキテクチャで緯度経度による検索するベストな方法は何なんでしょうか?誰か教えてください…