PHP
laravel
DynamoDB

laravel-dynamodb で Range Key の BETWEEN 条件を指定する際の注意

結論

  • where($rangeKeyName, 'range', [$min, $max]) を使おう
  • whereBetween() は無効

確認環境

事前条件

次のようなテーブルを考える。

Movies

AttributeName KeyType AttributeType
id HASH String
search_key String
date String
(以降は適宜必要な Attribute を指定する)

このテーブルには以下の GSI が設定されているとする。

IndexName HASH RANGE Projection
date_range search_key date ALL

また、 App\Models\MovieBaopham\DynamoDb\DynamoDbModel を継承した Model を定義しているものとする。

検証

search_key + date の GSI で date に BETWEEN を指定してデータを取得する。

(今回は GSI での検索になるが、Hash Key + Range Key テーブルや LSI でも同じだと考えられる)

:ok_woman: where(~,'between',~)

きちんと BETWEEN が指定されて、Query になっている。

>>>  App\Models\Movie::where('search_key', '1')->where('date', 'between', ['2017-01-01', '2018-01-01'])->toDynamoDbQuery()
=> BaoPham\DynamoDb\RawDynamoDbQuery {
     +op: "Query",
     +query: [
       "IndexName" => "date_range",
       "KeyConditionExpression" => "#search_key = :a1 AND (#date BETWEEN :a2 AND :a3)",
       "ExpressionAttributeNames" => [
         "#search_key" => "search_key",
         "#date" => "date",
       ],
       "ExpressionAttributeValues" => [
         ":a1" => [
           "S" => "1",
         ],
         ":a2" => [
           "S" => "2017-01-01",
         ],
         ":a3" => [
           "S" => "2018-01-01",
         ],
       ],
       "TableName" => "Movies",
     ],
   }

:no_good: whereBetween(~)

whereBetween() は無効なようで、Range Key での絞り込み条件が指定されずに Scan になってしまっている。

(例外投げてほしいなあ。。。)

>>> App\Models\Movie::where('search_key', '1')->whereBetween('date', ['2017-01-01', '2018-01-01'])->toDynamoDbQuery()
=> BaoPham\DynamoDb\RawDynamoDbQuery {
     +op: "Scan",
     +query: [
       "FilterExpression" => "#search_key = :a1",
       "ExpressionAttributeNames" => [
         "#search_key" => "search_key",
       ],
       "ExpressionAttributeValues" => [
         ":a1" => [
           "S" => "1",
         ],
       ],
       "TableName" => "Movies",
     ],
   }

:no_good: where(~)×2

単純に AND でつなげる。Scan になってしまう。

>>>  App\Models\Movie::where('search_key', '1')->where('date', '>', '2017-01-01')->where('date', '<', '2018-01-01')->toDynamoDbQuery()
=> BaoPham\DynamoDb\RawDynamoDbQuery {
     +op: "Scan",
     +query: [
       "FilterExpression" => "#search_key = :a1 AND #date > :a2 AND #date < :a3",
       "ExpressionAttributeNames" => [
         "#search_key" => "search_key",
         "#date" => "date",
       ],
       "ExpressionAttributeValues" => [
         ":a1" => [
           "S" => "1",
         ],
         ":a2" => [
           "S" => "2017-01-01",
         ],
         ":a3" => [
           "S" => "2018-01-01",
         ],
       ],
       "TableName" => "Movies",
     ],
   }