背景
DynamoDB のテーブルにて、複合ソートキーのテーブルがあった。
複数の属性を "#" で結合したソートキー、って聞いた。
当初は以下みたいな感じかと思った
- 自動で属性を選択したら ソートキーが出来る
- 選択した属性単位で上手く検索出来る
そしたら、以下だった・・
- 単なる文字列
- "#" 自身で Join/Split する
- もしくは、属性を別途作成して保存しておき利用する。
- 例
- timestamp#id <複合ソートキー
- timestamp
- id
- 例
ここで問題となるのが以下。で、この解消法を記録
属性 | 型 | Between | 理由 |
---|---|---|---|
timestamp#id | 文字列 | lower <= x < upper | その後に続く文字がある為、上限一致しない |
timestamp | 数値 | lower <= x <= upper | 数値であり、上限も一致する |
結論
数値側の上限を除外すればいいので、FilterExpression ではじくのが一番マシかな、と
単純に SK として使う場合は文字列
Index で timestamp: number を利用する場合には、上限を弾く
const paramsQuery = {
TableName: "User",
IndexName: "user-post-index",
ExpressionAttributeNames: {
"#PK": "uid",
"#SK": "timestamp",
"#SKupper": "timestamp#post_id", // Index では、単なる属性
},
ExpressionAttributeValues: {
":PK": "userID_0001",
":sortkeyval1": 1670550736983,
":sortkeyval2": 1670550736993,
":SKupper": "1670550736993", // sortkeyval2 の文字列化
},
KeyConditionExpression: "#PK =:PK AND ( #SK BETWEEN :sortkeyval1 AND :sortkeyval2 )",
FilterExpression: "#SKupper < :SKupper",
};
const users = (await ddbDocClient.send(new import_lib_dynamodb2.QueryCommand(paramsQuery)));
複合ソートキーは単なる文字列検索&ソートなんですね
この場合、時刻 + ID にすると意味は無くて、日付 + ID なら、かなぁ。この設計でいいんだろうか?という疑問が・・
説明にあった以下のような階層化のほうが分かりやすいね
[country]#[region]#[state]#[county]#[city]#[neighborhood]
検証
色々と試してみた記録
ソート
色々入れてみたけど、結局日付とか関係なしに、文字の先頭からの文字コードソートって感じ
故に、文字列書式で Zero padding とかちゃんとしておけば大丈夫って話
クエリ
文字列として検索するって考えれば、まぁ、普通。
EndsWith や Contains なんかもあればいいのに、とは思うけど。
条件 | 結果 | |
---|---|---|
次と等しい | ||
次以下 | NG | ![]() |
次よりも小さい | OK | ![]() |
次以上 | OK | ![]() |
次よりも大きい | NG | ![]() |
次の間 | 以上 + よりも小さい と考えるとOK | ![]() |
次で始まる | 普通に BeginsWith | ![]() |
あとがき
RDB とは違うんだよ、RDB とはって声が聞こえてくる感じ
色々学んでいく事が多いですね。
まずは、Lib.*Command を整理しておくところからかな