のーずいだんぷ

主に自分用メモですが、もしかしたら誰かの役に立つかもしれません

AWS DynamoDBでエラー[Invalid KeyConditionExpression: Syntax error; token: -, near]が発生する

何をしようとしたのか

Node.jsのAWS SDKを使用して、query( )を行いたかった。 (DocumentClientクラスを使用) 以下のようなparamを設定したところタイトルの通りのエラーが発生した。

エラー本文はプロダクトに関する情報があるため詳細なスタックトレースは割愛する。

エラー本文
{ ValidationException: Invalid KeyConditionExpression: Syntax error; token: "-", near: ":1212_***-test"
    at Request.extractError......
stackTrace.....
  message:
   'Invalid KeyConditionExpression: Syntax error; token: "-", near: ":1212_***-test"',
  code: 'ValidationException',
  time: 2019-10-07T23:08:32.414Z,
  requestId: '4D8198PHE**************************************',
  statusCode: 400,
  retryable: false,
  retryDelay: 41.67230422166851 }
メソッドに渡すパラメータ
const TABLE_NAME = 'sample_table;
let hash_key = "1212_***-test-sample";
let params = {
    TableName: TABLE_NAME,
    KeyConditionExpression:`sample_group =:${hash_key}`
};

結局原因は?

以下のissueにあるようにkeyにダッシュは使えないらしい。

github.com

対策した

以下のようにコードを変更して試してみた。

let params = {
    TableName: TABLE_NAME,
    ExpressionAttributeValues:{
        ":hash": "1212_***-test-sample",
        ":range": "test_id"
    },
    KeyConditionExpression:"sample_group = :hash AND sample_id = :range"
};

つまりどういうことなのか?

KeyConditionExpression には予約済みの用語や、先程のダッシュのように禁止されている記号は入力できない。 その場合、コードのようにExpressionAttributeValuesで別名を定義して代入する必要がある。 上記の例ではhash_key:hashに、range_key:rangeに別名が付けられたということになっている。

なお今の例では、クエリに渡す「値」を別名で置き換えたが、テーブルの「カラム名」自体が予約語に引っかかる場合もある。 その場合はExpressionAttributeNameで同じ要領で別名を定義してやると良い。 個人的には値にどんな値が入るか不明確なときにはExpressionAttributeValueを定義しておくほうが安全だと思う。