TableStoreの使い方
Alibaba CloudのNoSQLであるTableStoreを使います。
目標
以下に示すTableStoreの基本的な操作をnodejsから行います。
- テーブルの新規作成
- テーブル一覧の表示
- 行の作成
- 行の表示
- 複数行の表示
TableStoreとは
Alibaba CloudのNoSQLデータベースのサービスです。なんかもう公式の概要がめちゃくちゃ分かりやすいのでこっち載せておきます。
Table Storeの概要 - プロダクト概要| Alibaba Cloud ドキュメントセンター
準備
ドキュメントが最強なので基本はドキュメントに沿って進めます。
初期化 - 開発ガイド| Alibaba Cloud ドキュメントセンター
まずはRAMのユーザーに適切な権限を付与しておいてください。
次にTableStoreに新しくインスタンスを作ります。
画面でポチポチしてインスタンスを作ります。
「sampleStore」をクリックしてインスタンスの画面に入ります。
次に、VPCをバインドすれば準備完了です。
クライアントの作成
TableStoreの操作に使うクライアントオブジェクトを作成します。
// client.js const TableStore = require('tablestore') const instanceName = 'sampleStore' const client = new TableStore.Client({ accessKeyId: ’LTAxxxxxxxxxxxx’, secretAccessKey: ’Rztxxxxxxxxxxxxxxxxxxxx’, endpoint: `https://${instanceName}.cn-xxxxxx.ots.aliyuncs.com`, instancename: instanceName, }) console.log(client)
node clinet.js
でこのプログラムを実行します。
$ node list.js Client { config: Config { accessKeyId: 'LTAxxxxxxxxxxxx', secretAccessKey: 'Rzxxxxxxxxxxxxxxxxxxxxxxx', accessKeySecret: null, stsToken: null, securityToken: null, logger: null, endpoint: 'https://teststorage.cn-xxxxxxx.ots.aliyuncs.com', httpOptions: {}, maxRetries: undefined, instancename: 'teststorage', computeChecksums: true } }
初期化 - 開発ガイド| Alibaba Cloud ドキュメントセンター
テーブルの新規作成(createTable())
sampleTableという名前のテーブルを作成します。プライマリキーにはid: INTEGERを設定します。
// createTable.js const TableStore = require('tablestore') const instanceName = 'sampleStore' const client = new TableStore.Client({ accessKeyId: ’LTAxxxxxxxxxxxx’, secretAccessKey: ’Rztxxxxxxxxxxxxxxxxxxxx’, endpoint: `https://${instanceName}.cn-xxxxxx.ots.aliyuncs.com`, instancename: instanceName, }) const params = { tableMeta: { tableName: 'sampleTable', primaryKey: [ { name: 'id', type: 'INTEGER' } ] }, reservedThroughput: { capacityUnit: { read: 0, write: 0 } }, tableOptions: { timeToLive: -1, maxVersions: 1 } } client.createTable(params, (err, data) => { if (err) { console.log('error:', err) return } console.log('success:', data) })
今の仕様だと特に返ってくるものはありません。
$ node createTable.js success: { RequestId: '00000000-xxxx-xxxx-xxxx-xxxxxxxxxxxx' }
テーブル一覧の表示(listTable())
作ったテーブルの一覧を返します。
// listTable.js const TableStore = require('tablestore') const instanceName = 'sampleStore' const client = new TableStore.Client({ accessKeyId: ’LTAxxxxxxxxxxxx’, secretAccessKey: ’Rztxxxxxxxxxxxxxxxxxxxx’, endpoint: `https://${instanceName}.cn-xxxxxx.ots.aliyuncs.com`, instancename: instanceName, }) client.listTable({}, (err, data) => { if (err) { console.log('error:', err) return } console.log('success:', data) })
実行するとちゃんと先ほど作ったテーブルの名前が返ってきます。
$ node listTable.js success: { table_names: [ 'sampleTable' ], RequestId: '00000000-xxxx-xxxx-xxxx-xxxxxxxxxxxx' }
行の作成(putRow())
paramsのconditionにRowExistenceExpectation.IGNORE
を指定すると、既に保存されている行の中に指定するprimaryKeyと同じものがある場合内容が上書きされます。
RowExistenceExpectation.EXPECT_NOT_EXIST
だと同じものがない時のみデータが挿入されます。
primaryKeyは自動でインクリメントするかユニークキーを発行して欲しいのですが、ユーザー側でよしなにするしかないのでしょうかね
// createRow.js const TableStore = require('tablestore') const Long = TableStore.Long const currentTimeStamp = Date.now() const instanceName = 'sampleStore' const client = new TableStore.Client({ accessKeyId: ’LTAxxxxxxxxxxxx’, secretAccessKey: ’Rztxxxxxxxxxxxxxxxxxxxx’, endpoint: `https://${instanceName}.cn-xxxxxx.ots.aliyuncs.com`, instancename: instanceName, }) const params = { tableName: 'sampleTable', condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, null), primaryKey: [{ 'id': Long.fromNumber(1) }], attributeColumns: [ { 'name': 'Table Store' }, { 'created_at': currentTimeStamp } ], returnContent: { returnType: TableStore.ReturnType.Primarykey } } client.putRow(params, (err, data) => { if (err) { console.log('error:', err) return } console.log('success:', data) })
作ったデータの内容が返ってきます。
$ node createRow.js success: { consumed: { capacity_unit: { read: 0, write: 1 } }, row: { primaryKey: [ [Object] ], attributes: [] }, RequestId: '00000000-xxxx-xxxx-xxxx-xxxxxxxxxxxx' }
attributesが空なのはバグ?
行の表示(getRow())
conditionを使うと他の列での検索もできます。
// getRow.js const TableStore = require('tablestore') const Long = TableStore.Long const currentTimeStamp = Date.now() const instanceName = 'sampleStore' const client = new TableStore.Client({ accessKeyId: ’LTAxxxxxxxxxxxx’, secretAccessKey: ’Rztxxxxxxxxxxxxxxxxxxxx’, endpoint: `https://${instanceName}.cn-xxxxxx.ots.aliyuncs.com`, instancename: instanceName, }) var params = { tableName: 'sampleTable', primaryKey: [{ 'id': Long.fromNumber(1) }], maxVersions: 2 } client.getRow(params, (err, data) => { if (err) { console.log('error:', err) return } console.log('success:', data) console.log(data.row.attributes) })
data.row
に取得した行が格納されています。
$ node getRow.js success: { consumed: { capacity_unit: { read: 1, write: 0 } }, row: { primaryKey: [ [Object] ], attributes: [ [Object], [Object] ] }, next_token: null, RequestId: '00000000-xxxx-xxxx-xxxx-xxxxxxxxxxxx' } [ { columnName: 'created_at', columnValue: 1531110991789, timestamp: Int64 { buffer: <Buffer 59 a9 53 7d 64 01 00 00>, offset: 0 } }, { columnName: 'name', columnValue: 'Table Store', timestamp: Int64 { buffer: <Buffer 59 a9 53 7d 64 01 00 00>, offset: 0 } } ]
複数行の表示(batchGetRow())
複数行を表示するbatchGetRow()の処理は、ちょっとクセがあります。以下のコードは内容はサンプル通りなのですがちょっとJSっぽく書き換えています。
複数行操作 - 開発ガイド| Alibaba Cloud ドキュメントセンター
const TableStore = require('tablestore') const Long = TableStore.Long const currentTimeStamp = Date.now() const instanceName = 'sampleStore' const maxRetryTimes = 3 const retryCount = 0 const client = new TableStore.Client({ accessKeyId: ’LTAxxxxxxxxxxxx’, secretAccessKey: ’Rztxxxxxxxxxxxxxxxxxxxx’, endpoint: `https://${instanceName}.cn-xxxxxx.ots.aliyuncs.com`, instancename: instanceName, }) const params = { tables: [{ tableName: 'sampleTable', primaryKey: [ [{ 'id': Long.fromNumber(1) }] ], startColumn: 'created_at', endColumn: 'name' }] } function batchGetRow(params) { client.batchGetRow(params, (err, data) => { if (err) { console.log('error:', err) return } var isAllSuccess = true var retryRequest = { tables: [] } data.tables.forEach(tables => { let failedRequest = { tableName: tables[0].tableName, primaryKey: [] }; tables.forEach(table => { // if the action is failed if (!table.isOk && table.primaryKey !== undefined) { isAllSuccess = false let pks = [] table.primaryKey.forEach(primaryKey => { const name = primaryKey.name const value = primaryKey.value let kp = {} kp[name] = value pks.push(kp) }) failedRequest.primaryKey.push(pks) } }) }) if (!isAllSuccess && retryCount++ < maxRetryTimes) { batchGetRow(retryRequest) } console.log(data.tables[0][0]) console.log(data.tables[0][0].capacityUnit) console.log(data.tables[0][0].attributes) console.log(data.tables[0][0].primaryKey) }) } batchGetRow(params, maxRetryTimes)
えっリトライ処理もユーザーが書かなきゃいけないの
めっちゃ薄いなあ
$ node getBatchRow.js { isOk: true, errorCode: null, errorMessage: null, tableName: 'sampleTable', capacityUnit: { read: 1, write: 0 }, primaryKey: [ { name: 'id', value: [Int64] } ], attributes: [ { columnName: 'created_at', columnValue: 1531110991789, timestamp: [Int64] } ] } { read: 1, write: 0 } [ { columnName: 'created_at', columnValue: 1531110991789, timestamp: Int64 { buffer: <Buffer 59 a9 53 7d 64 01 00 00>, offset: 0 } } ] [ { name: 'id', value: Int64 { buffer: <Buffer 01 00 00 00 00 00 00 00>, offset: 0 } } ]
data.tables[0][0].attributes
に取得したデータが入っています。
環境
$ node --version
v10.6.0
まとめ
公式ドキュメントが分かりやすくて特に詰まることなくできた。
正しいけど難しいことがダラダラ書かれているドキュメントより最低限のことがズバッと書かれているドキュメントの方が分かりやすい。