LoginSignup
5
4

More than 5 years have passed since last update.

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

Posted at

結論

  • 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",
     ],
   }
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4