AWS DynamoDBのqueryで「The provided starting key does not match the range key predicate」エラー
KeyConditionExpression
でソートキーを範囲指定 (>=
など) してる時に、ExclusiveStartKey
で指定した開始位置が、範囲指定のスタート位置より外側である場合に発生する。
↓こういうの。そういえば以前は、DynamoDBのソートキーはレンジキーって呼ばれてたんだっけ。
具体的には、以下のようなパラメータでqueryしたら出てくる。
パーティションキーは同値だからここでは触れないものとして、このパラメータの意味は以下の通りになる。
KeyConditionExpression
では、created_at
が1999-07-31T00:00:10.000Z
以上のデータを探したい。ExclusiveStartKey
では、created_at
が1999-07-31T00:00:09.000Z
の次のデータから開始したい。
名前の通り、ExclusiveStartKey
は指定したキーの『次』の値から読み取るためのオプションだ。範囲外なら ExclusiveStartKey
は無視してくれればと思うのだが、DynamoDB的にはダメなようだ。
なので KeyConditionExpression
で範囲指定しながら ExclusiveStartKey
を使うときは、ExclusiveStartKey
で指定するソートキーが KeyConditionExpression
の範囲内であることを、事前にチェックしておく必要がある。
↓のように、:c
と ExclusiveStartKey.created_at
を同値に変更した場合はエラーにならない。
1999-07-31T00:00:10.000Z
以上のデータを探すために 1999-07-31T00:00:10.000Z
の『次』から開始するのは、範囲内に収まってるからOK。むしろ、ジャスト 1999-07-31T00:00:10.000Z
のデータは引っかからないし。
なお、この範囲の判定は ScanIndexForward
の影響を受けるので注意。上記のパラメータに ScanIndexForward: false
を追加する↓と、またエラーが出るようになる。
ExclusiveStartKey
は指定したキーの次の項目から読み始めるものなので、降順の時は逆転するからだ。降順のとき、1999-07-31T00:00:10.000Z
の『次』のデータはそれより昔ということになり、KeyConditionExpression
の範囲外になる。
……が、個人的に首を捻ってしまったのは↓の場合。(昇順)
これはエラーになる。なるのだが……
KeyConditionExpression
では、created_at
が1999-07-31T00:00:10.000Z
より上のデータを探したい。ExclusiveStartKey
では、created_at
が1999-07-31T00:00:10.000Z
の次のデータから開始したい。
……確かに自明すぎて ExclusiveStartKey
を設定する意味が皆無だけど、ギリギリ範囲外ではないような? 問題にされてるのは、実際の開始位置より ExclusiveStartKey
自体の位置ということだろうか。
DynamoDBの中身とかを知ればしっくりくるのかもしれないけど、とりあえず今は「DynamoDBは明らかにおかしいこと (範囲外) を言われるのが嫌いだし、分かり切ってることを回りくどく (>
& ジャストExclusiveStartKey
) 言われるのも嫌い」と思うことにした。
以上。