Node.jsでDynamoDBを触ってみたので、備忘録として残しておきます。
プライマリーキーとして、パーティションキーのみの方法と、パーティションキー+ソートキーでユニークにする方法があります。
前者を「ハッシュキーテーブル」、後者を「複合キーテーブル」と呼ぶことにします。
以下、参考にさせていただきました。(ありがとうございました)
コンセプトから学ぶAmazon DynamoDB【インデックス俯瞰篇】
【詳解】JavascriptでDynamoDBを操作する
DynamoDB での Node.js の開始方法
Class: AWS.DynamoDB.DocumentClient
準備
Node.jsのソースコードのどこかに、以下を記載しておきます。
constAWS=require("aws-sdk");AWS.config.update({region:"ap-northeast-1",});constdocClient=newAWS.DynamoDB.DocumentClient();
以降で、上記の変数docClientを使います。
それから、AWS Lambdaではなく自身のサーバ等で実行する場合は、以下と、aws configure
でIAMの認証情報を設定しておきます。
npm install aws-sdk
ハッシュキーテーブル
プライマリキーがパーティションキーのみのハッシュキーテーブルを扱います。
こんな感じでテーブルを作成します。
テーブル名(tableName):Hashkey_Table
パーティションキー名:firstkey
登録
項目を登録します。SQLでいうところのInsertです。
varparams_put={TableName:tableName,Item:{firstkey:"firstvalue_1","attr":"Hello_1",},ConditionExpression:'attribute_not_exists(firstkey)',};result=awaitdocClient.put(params_put).promise();
Itemのところに、登録したい項目の値を指定します。スキーマレスなので、任意の値(attr=”Hello_1”)も指定しています。ただし、プライマリキーは必ず指定する必要があります。
以下の指定はオプションです。指定した場合は、プライマリキーが同じ項目が登録されていた場合はエラー(throwが発生)となります。指定しなかった場合は、置き換わります。
ConditionExpression: "attribute_not_exists(firstkey)"
取得
プライマリキーを指定して、項目を取得します。
SQLと違って、1件のみ取得します。
varparams_get={TableName:tableName,Key:{firstkey:"firstvalue_1"}};result=awaitdocClient.get(params_get).promise();if(result.Item){console.log(JSON.stringify(result.Item));}else{// 見つからない場合はundefinedconsole.log('Not found');}
更新
SQLでいうところのUPDATEです。
登録時に一緒に指定したattrの値を変更します。
varparams_update={TableName:tableName,Key:{firstkey:"firstvalue_1"},ExpressionAttributeNames:{'#attr':'attr'},ExpressionAttributeValues:{':attrValue':'Hello_1_Update_1'},UpdateExpression:'SET #attr = :attrValue',ConditionExpression:"attribute_exists(firstkey)",ReturnValues:"ALL_NEW"};result=awaitdocClient.update(params_update).promise();
以下の指定はオプションです。指定した場合は、もし更新対象の項目が存在しなかった場合はエラー(throwが発生)となります。指定しなかった場合で、もし更新対象が項目が存在しなかった場合は、新規に登録されます。
ConditionExpression: "attribute_exists(firstkey)"
以下もオプションです。指定すると、更新した項目の全体の値が返ってきます。
ReturnValues:"ALL_NEW"
削除
指定したプライマリキーに合致する項目を削除します。
varparams_delete={TableName:tableName,Key:{firstkey:"firstvalue_1"},// ConditionExpression: 'attribute_exists(firstkey)',};result=awaitdocClient.delete(params_delete).promise();
以下の指定はオプションです。もし指定した場合は、指定したプライマリキーに合致した項目がなかった場合にエラー(throw)となります。
ConditionExpression: "attribute_exists(firstkey)"
一括取得
先ほどの取得は、1件のプライマリキーを指定して、合致する1件の項目を取得しました。
今度は、複数のプライマリキーを指定して、合致する複数の項目を取得します。
varparams_batchget={RequestItems:{}};params_batchget.RequestItems[tableName]={Keys:[{firstkey:"firstvalue_2"},{firstkey:"firstvalue_3"},]};result=awaitdocClient.batchGet(params_batchget).promise();if(Object.keys(result.UnprocessedKeys).length>0)console.log('in process yet');for(vari=0;i<result.Responses[tableName].length;i++){console.log(i,JSON.stringify(result.Responses[tableName][i]));}
レスポンスのresult.Responses[tableName]
に合致した項目が配列で格納されています。
もし、result.UnprocessedKeys
に何か値が入っていると、全部の検索は完了していないため、再度取得をしないといけないようです。
複合キーテーブル
今度は、プライマリキーがパーティションキー+ソートキーの複合キーテーブルを扱います。
こんな感じでテーブルを作成します。
テーブル名(tableName):Complexkey_Table
パーティションキー名:firstkey
ソートキー名:secondkey
こんな感じで作ります。
登録
項目を登録します。
varparams_put={TableName:tableName,Item:{firstkey:"firstvalue_1",secondkey:"secondvalue_1","attr":"Hello_1",},ConditionExpression:'attribute_not_exists(firstkey)',};result=awaitdocClient.put(params_put).promise();
ハッシュキーテーブルと同様、Itemに項目の値を指定します。
プライマリキーとソートキーでユニークとなるため、両方を指定する必要があります。
取得
項目を取得します。
1つの項目が返る前提ですので、ユニークに特定するため、プライマリキーとソートキーの両方を指定します。
varparams_get={TableName:tableName,Key:{firstkey:"firstvalue_1",secondkey:"secondvalue_1",}};result=awaitdocClient.get(params_get).promise();if(result.Item){console.log(JSON.stringify(result.Item));}else{// 見つからない場合はundefinedconsole.log('Not found');}
一括取得
複数のプライマリキーを指定して、合致する複数の項目を一度に取得します。
varparams_batchget={RequestItems:{}};params_batchget.RequestItems[tableName]={Keys:[{firstkey:'firstvalue_1',secondkey:'secondvalue_1',},{firstkey:'firstvalue_2',secondkey:"secondvalue_2",},{firstkey:"firstvalue_3",secondkey:'secondvalue_3',},],};varresult=awaitdocClient.batchGet(params_batchget).promise();if(Object.keys(result.UnprocessedKeys).length>0)console.log('in process yet');for(vari=0;i<result.Responses[tableName].length;i++){console.log(i,JSON.stringify(result.Responses[tableName][i]));}
更新
項目の値を更新します。
ハッシュキーテーブルの時とほぼ同じです。
プライマリキーとして、パーティションキーとソートキーの両方を指定しています。
varparams_update={TableName:tableName,Key:{firstkey:"firstvalue_1",secondkey:"secondvalue_1",},ExpressionAttributeNames:{'#attr':'attr'},ExpressionAttributeValues:{':attrValue':'Hello_1_Update_1'},UpdateExpression:'SET #attr = :attrValue',ConditionExpression:'attribute_exists(firstkey)',ReturnValues:"ALL_NEW"};result=awaitdocClient.update(params_update).promise();
削除
項目の削除です。
ハッシュキーテーブルの時とほぼ同じです。
プライマリキーとして、パーティションキーとソートキーの両方を指定しています。
varparams_delete={TableName:tableName,Key:{firstkey:'firstvalue_1',secondkey:'secondvalue_1',},// ConditionExpression: 'attribute_exists(firstkey)',};result=awaitdocClient.delete(params_delete).promise();
検索
条件に合致する項目を検索します。
取得と違って、複数の項目が返ってきます。
まず最初が、パーティションキーが合致する項目の取得です。
複合キーテーブルでは、パーティションキーとソートキーでユニークとするため、同じパーティションキーで、値の異なる複数のソートキーを登録することができます。
よって、パーティションキーのみを条件に指定した場合は、同じパーティションキーの複数の項目を取得できます。
varparams_query={TableName:tableName,ExpressionAttributeNames:{'#firstkey':'firstkey',},ExpressionAttributeValues:{':firstValue':"firstvalue_1",},KeyConditionExpression:'#firstkey = :firstValue',};result=awaitdocClient.query(params_query).promise();for(vari=0;i<result.Count;i++){console.log(i,JSON.stringify(result.Items[i]));}
result.Count
には取得した項目の件数、result.Items
に取得した項目が配列で取得できます。
次は、ソートキーにさらに条件を付けて絞り込んで検索します。
varparams_query={TableName:tableName,ExpressionAttributeNames:{'#firstkey':'firstkey','#secondkey':'secondkey',},ExpressionAttributeValues:{':firstValue':'firstvalue_1',':secondValue':'secondvalue_1_',},KeyConditionExpression:'#firstkey = :firstValue AND begins_with(#secondkey, :secondValue)',};result=awaitdocClient.query(params_query).promise();for(vari=0;i<result.Count;i++){console.log(i,JSON.stringify(result.Items[i]));}
上記では1例として、以下を指定しています。
begins_with(#secondkey, :secondValue)
これは、ソートキーが、指定した値secondvalue_1_
で始まる文字列の場合に合致したとみなされます。
(参考) DynamoDB でのクエリの操作
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Query.html
終わりに
DynamoDBには、セカンダリインデックスという機能がありますが、また今度。
以上