MochiuWiki : SUSE, EC, PCB
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtの応用 - AWS DynamoDBのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtの応用 - AWS DynamoDB
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == AWS DynamoDBは、AWSが提供するフルマネージド型のNoSQLデータベースサービスである。<br> キー・バリュー型およびドキュメント型のデータモデルをサポートし、高速で予測可能なパフォーマンスとシームレスなスケーラビリティを実現する。<br> <br> 主な特徴を以下に示す。<br> * フルマネージド *: サーバ管理、ソフトウェアパッチ、セットアップ不要 * 高パフォーマンス *: 一桁ミリ秒のレスポンスタイム * 自動スケーリング *: トラフィックに応じて自動的に容量を調整 * 高可用性 *: 複数のAZに自動的にデータを複製 * 柔軟なスキーマ *: 各アイテムが異なる属性を持つことが可能 <br> AWS DynamoDBのデータモデルを以下に示す。<br> * テーブル *: データを格納する最上位のコンテナ * アイテム *: テーブル内の個々のレコード * 属性 *: アイテムを構成するデータフィールド (カラムに相当) * プライマリキー *: パーティションキー (必須) と ソートキー (オプション) で構成 <br> AWS DynamoDBは永続的な無料利用枠を提供しており、個人利用や小規模なアプリケーションであれば無料枠内で運用できることが多い。<br> <br><br> == AWS SDK for C++のインストール == [[Qtの応用_-_AWS|Qtの応用_-_AWS#AWS_SDK_for_C++のインストール]]のページを参照すること。<br> <br><br> == 1件のデータ挿入 : PutItem == テーブルに新しいアイテムを追加する。<br> <br> <syntaxhighlight lang="c++"> // アイテムを挿入 Aws::DynamoDB::Model::PutItemRequest putReq; putReq.SetTableName(tableName); putReq.AddItem("id", toAttr(1)); putReq.AddItem("name", toAttr("Taro Yamada")); putReq.AddItem("age", toAttr(30)); putReq.AddItem("email", toAttr("taro@example.com")); auto putResult = client.PutItem(putReq); if (putResult.IsSuccess()) { qDebug() << "✓ Item inserted successfully"; } else { qDebug() << "✗ Error: " << QString::fromStdString(putResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == 1件のデータ取得 :GetItem == プライマリキーを指定して1件のアイテムを取得する。<br> <br> <syntaxhighlight lang="c++"> // プライマリキーでアイテムを取得 Aws::DynamoDB::Model::GetItemRequest getReq; getReq.SetTableName(tableName); getReq.AddKey("id", toAttr(1)); auto getResult = client.GetItem(getReq); if (getResult.IsSuccess()) { const auto& item = getResult.GetResult().GetItem(); if (!item.empty()) { printItem(item); } else { qDebug() << "Item not found"; } } else { qDebug() << "✗ Error: " << QString::fromStdString(getResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == 複数件のデータ取得 : Query == パーティションキーを条件として複数件のアイテムを取得する。<br> <br> <syntaxhighlight lang="c++"> // クエリで複数件取得 (パーティションキーでフィルタ) Aws::DynamoDB::Model::QueryRequest queryReq; queryReq.SetTableName(tableName); queryReq.SetKeyConditionExpression("id = :value"); queryReq.AddExpressionAttributeValues(":value", toAttr(1)); // オプション : 取得件数制限 queryReq.SetLimit(10); auto queryResult = client.Query(queryReq); if (queryResult.IsSuccess()) { const auto& items = queryResult.GetResult().GetItems(); qDebug() << "Found" << items.size() << "items"; for (const auto& item : items) { printItem(item); } } else { qDebug() << "✗ Error: " << QString::fromStdString(queryResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == ソートキー条件を含むクエリ == パーティションキーとソートキーを組み合わせた条件でデータを取得する。<br> <br> <syntaxhighlight lang="c++"> // パーティションキーとソートキーでクエリ Aws::DynamoDB::Model::QueryRequest queryReq; queryReq.SetTableName(tableName); // 例: userId = 100 かつ timestamp > 1234567890 queryReq.SetKeyConditionExpression("userId = :uid AND #ts > :time"); // 属性名のエイリアス(予約語の場合に使用) queryReq.AddExpressionAttributeNames("#ts", "timestamp"); // 属性値 queryReq.AddExpressionAttributeValues(":uid", toAttr(100)); queryReq.AddExpressionAttributeValues(":time", toAttr(1234567890)); auto queryResult = client.Query(queryReq); if (queryResult.IsSuccess()) { const auto& items = queryResult.GetResult().GetItems(); qDebug() << "Found" << items.size() << "items"; for (const auto& item : items) { printItem(item); } } </syntaxhighlight> <br><br> == 全件取得 : Scan == テーブル内の全アイテムをスキャンして取得する。<br> <br> <u>Scanは全テーブルスキャンのため、大量データには使用しない。</u><br> <u>Queryを優先すること。</u><br> <br> <syntaxhighlight lang="c++"> // テーブル全体をスキャン Aws::DynamoDB::Model::ScanRequest scanReq; scanReq.SetTableName(tableName); // オプション: 取得件数制限 scanReq.SetLimit(100); auto scanResult = client.Scan(scanReq); if (scanResult.IsSuccess()) { const auto& items = scanResult.GetResult().GetItems(); qDebug() << "Found" << items.size() << "items"; for (const auto& item : items) { printItem(item); } } else { qDebug() << "✗ Error: " << QString::fromStdString(scanResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == フィルタ条件付きスキャン == スキャン時に特定の条件でフィルタリングする。<br> <br> <syntaxhighlight lang="c++"> // 条件付きスキャン(例: age > 25) Aws::DynamoDB::Model::ScanRequest scanReq; scanReq.SetTableName(tableName); scanReq.SetFilterExpression("age > :minAge"); scanReq.AddExpressionAttributeValues(":minAge", toAttr(25)); auto scanResult = client.Scan(scanReq); if (scanResult.IsSuccess()) { const auto& items = scanResult.GetResult().GetItems(); qDebug() << "Found" << items.size() << "items with age > 25"; for (const auto& item : items) { printItem(item); } } </syntaxhighlight> <br><br> == データの更新 : UpdateItem == 既存のアイテムの属性を更新する。<br> <br> <syntaxhighlight lang="c++"> // アイテムを更新 Aws::DynamoDB::Model::UpdateItemRequest updateReq; updateReq.SetTableName(tableName); updateReq.AddKey("id", toAttr(1)); // 更新式: SET age = 31, email = "new@example.com" updateReq.SetUpdateExpression("SET age = :newAge, email = :newEmail"); updateReq.AddExpressionAttributeValues(":newAge", toAttr(31)); updateReq.AddExpressionAttributeValues(":newEmail", toAttr("new@example.com")); auto updateResult = client.UpdateItem(updateReq); if (updateResult.IsSuccess()) { qDebug() << "✓ Item updated successfully"; } else { qDebug() << "✗ Error: " << QString::fromStdString(updateResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == 条件付き更新 == 特定の条件を満たす場合のみ更新を実行する。<br> <br> <syntaxhighlight lang="c++"> // 条件付き更新(例: ageが30の場合のみ更新) Aws::DynamoDB::Model::UpdateItemRequest updateReq; updateReq.SetTableName(tableName); updateReq.AddKey("id", toAttr(1)); updateReq.SetUpdateExpression("SET age = :newAge"); updateReq.AddExpressionAttributeValues(":newAge", toAttr(31)); // 条件式 updateReq.SetConditionExpression("age = :currentAge"); updateReq.AddExpressionAttributeValues(":currentAge", toAttr(30)); auto updateResult = client.UpdateItem(updateReq); if (updateResult.IsSuccess()) { qDebug() << "✓ Conditional update succeeded"; } else { if (updateResult.GetError().GetErrorType() == Aws::DynamoDB::DynamoDBErrors::CONDITIONAL_CHECK_FAILED) { qDebug() << "Condition not met - update skipped"; } else { qDebug() << "✗ Error: " << QString::fromStdString(updateResult.GetError().GetMessage()); } } </syntaxhighlight> <br><br> == データの削除 : DeleteItem == プライマリキーを指定してアイテムを削除する。<br> <br> <syntaxhighlight lang="c++"> // アイテムを削除 Aws::DynamoDB::Model::DeleteItemRequest delReq; delReq.SetTableName(tableName); delReq.AddKey("id", toAttr(1)); auto delResult = client.DeleteItem(delReq); if (delResult.IsSuccess()) { qDebug() << "✓ Item deleted successfully"; } else { qDebug() << "✗ Error: " << QString::fromStdString(delResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == 条件付き削除 == 特定の条件を満たす場合のみ削除を実行する。<br> <br> <syntaxhighlight lang="c++"> // 条件付き削除 // 例: statusが"inactive"の場合のみ削除 Aws::DynamoDB::Model::DeleteItemRequest delReq; delReq.SetTableName(tableName); delReq.AddKey("id", toAttr(1)); delReq.SetConditionExpression("#status = :statusValue"); delReq.AddExpressionAttributeNames("#status", "status"); delReq.AddExpressionAttributeValues(":statusValue", toAttr("inactive")); auto delResult = client.DeleteItem(delReq); if (delResult.IsSuccess()) { qDebug() << "✓ Conditional delete succeeded"; } else { if (delResult.GetError().GetErrorType() == Aws::DynamoDB::DynamoDBErrors::CONDITIONAL_CHECK_FAILED) { qDebug() << "Condition not met - delete skipped"; } } </syntaxhighlight> <br><br> == バッチ書き込み : BatchWriteItem == 複数のアイテムを1度に挿入または削除する。<br> BatchWriteItemは最大25件まで1度に処理可能である。<br> <br> <syntaxhighlight lang="c++"> #include <aws/dynamodb/model/BatchWriteItemRequest.h> #include <aws/dynamodb/model/WriteRequest.h> // バッチ書き込み Aws::DynamoDB::Model::BatchWriteItemRequest batchReq; // 複数のPutRequestを作成 std::vector<Aws::DynamoDB::Model::WriteRequest> writeRequests; for (int i = 1; i <= 5; i++) { Aws::DynamoDB::Model::PutRequest putRequest; Aws::Map<Aws::String, Aws::DynamoDB::Model::AttributeValue> item; item["id"] = toAttr(i); item["name"] = toAttr(QString("User %1").arg(i)); item["age"] = toAttr(20 + i); putRequest.SetItem(item); Aws::DynamoDB::Model::WriteRequest writeReq; writeReq.SetPutRequest(putRequest); writeRequests.push_back(writeReq); } batchReq.AddRequestItems(tableName, writeRequests); auto batchResult = client.BatchWriteItem(batchReq); if (batchResult.IsSuccess()) { qDebug() << "✓ Batch write completed"; // 未処理のアイテムがあるか確認 const auto& unprocessed = batchResult.GetResult().GetUnprocessedItems(); if (!unprocessed.empty()) { qDebug() << "Warning: Some items were not processed"; } } else { qDebug() << "✗ Error: " << QString::fromStdString(batchResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == バッチ読み込み : BatchGetItem == 複数のアイテムを1度に取得する。<br> <br> <syntaxhighlight lang="c++"> #include <aws/dynamodb/model/BatchGetItemRequest.h> #include <aws/dynamodb/model/KeysAndAttributes.h> // バッチ取得 Aws::DynamoDB::Model::BatchGetItemRequest batchGetReq; Aws::DynamoDB::Model::KeysAndAttributes keysAndAttrs; // 取得したいキーのリストを作成 std::vector<Aws::Map<Aws::String, Aws::DynamoDB::Model::AttributeValue>> keys; for (int i = 1; i <= 3; i++) { Aws::Map<Aws::String, Aws::DynamoDB::Model::AttributeValue> key; key["id"] = toAttr(i); keys.push_back(key); } keysAndAttrs.SetKeys(keys); batchGetReq.AddRequestItems(tableName, keysAndAttrs); auto batchGetResult = client.BatchGetItem(batchGetReq); if (batchGetResult.IsSuccess()) { const auto& responses = batchGetResult.GetResult().GetResponses(); for (const auto& tablePair : responses) { qDebug() << "Table:" << QString::fromStdString(tablePair.first); qDebug() << "Items count:" << tablePair.second.size(); for (const auto& item : tablePair.second) { printItem(item); } } } else { qDebug() << "✗ Error: " << QString::fromStdString(batchGetResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == ページネーション (継続トークン) == 大量のデータを取得する際に、ページネーションを使用して分割取得する。<br> <br> <syntaxhighlight lang="c++"> // ページネーション付きスキャン Aws::DynamoDB::Model::ScanRequest scanReq; scanReq.SetTableName(tableName); scanReq.SetLimit(10); // 1ページあたり10件 Aws::Map<Aws::String, Aws::DynamoDB::Model::AttributeValue> lastKey; int pageNum = 1; do { if (!lastKey.empty()) { scanReq.SetExclusiveStartKey(lastKey); } auto scanResult = client.Scan(scanReq); if (scanResult.IsSuccess()) { const auto& items = scanResult.GetResult().GetItems(); qDebug() << "\n=== Page" << pageNum << "===" << items.size() << "items"; for (const auto& item : items) { printItem(item); } // 次のページがあるか確認 lastKey = scanResult.GetResult().GetLastEvaluatedKey(); pageNum++; } else { qDebug() << "✗ Error: " << QString::fromStdString(scanResult.GetError().GetMessage()); break; } } while (!lastKey.empty()); qDebug() << "Total pages processed:" << (pageNum - 1); </syntaxhighlight> <br><br> == トランザクション書き込み : TransactWriteItems == 複数の操作をトランザクションとして実行する。(全成功または全失敗)<br> <br> <u>トランザクションは最大100項目まで可能である。</u><br> <br> <syntaxhighlight lang="c++"> #include <aws/dynamodb/model/TransactWriteItemsRequest.h> #include <aws/dynamodb/model/TransactWriteItem.h> // トランザクション書き込み Aws::DynamoDB::Model::TransactWriteItemsRequest transactReq; std::vector<Aws::DynamoDB::Model::TransactWriteItem> transactItems; // アイテム1: 挿入 Aws::DynamoDB::Model::TransactWriteItem item1; Aws::DynamoDB::Model::Put put1; Aws::Map<Aws::String, Aws::DynamoDB::Model::AttributeValue> newItem; newItem["id"] = toAttr(100); newItem["name"] = toAttr("Transaction User"); newItem["balance"] = toAttr(1000); put1.SetTableName(tableName); put1.SetItem(newItem); item1.SetPut(put1); transactItems.push_back(item1); // アイテム2: 更新 Aws::DynamoDB::Model::TransactWriteItem item2; Aws::DynamoDB::Model::Update update2; update2.SetTableName(tableName); Aws::Map<Aws::String, Aws::DynamoDB::Model::AttributeValue> key2; key2["id"] = toAttr(101); update2.SetKey(key2); update2.SetUpdateExpression("SET balance = balance - :amount"); update2.AddExpressionAttributeValues(":amount", toAttr(100)); item2.SetUpdate(update2); transactItems.push_back(item2); transactReq.SetTransactItems(transactItems); auto transactResult = client.TransactWriteItems(transactReq); if (transactResult.IsSuccess()) { qDebug() << "✓ Transaction completed successfully"; } else { qDebug() << "✗ Transaction failed: " << QString::fromStdString(transactResult.GetError().GetMessage()); } </syntaxhighlight> <br><br> == エラーハンドリング == DynamoDB操作時の一般的なエラーハンドリングパターンを以下に示す。<br> <br> <syntaxhighlight lang="c++"> auto result = client.GetItem(getReq); if (!result.IsSuccess()) { const auto& error = result.GetError(); switch (error.GetErrorType()) { case Aws::DynamoDB::DynamoDBErrors::RESOURCE_NOT_FOUND: qDebug() << "テーブルが見つかりません"; break; case Aws::DynamoDB::DynamoDBErrors::PROVISIONED_THROUGHPUT_EXCEEDED: qDebug() << "スループット制限を超えました。リトライしてください。"; break; case Aws::DynamoDB::DynamoDBErrors::CONDITIONAL_CHECK_FAILED: qDebug() << "条件チェックに失敗しました"; break; case Aws::DynamoDB::DynamoDBErrors::VALIDATION: qDebug() << "入力検証エラー: " << QString::fromStdString(error.GetMessage()); break; default: qDebug() << "エラー: " << QString::fromStdString(error.GetMessage()); break; } } </syntaxhighlight> <br><br> == サンプルコード == 以下の例では、AWS DynamoDBにアクセスしてデータを取得、挿入、更新、削除している。<br> <br> <syntaxhighlight lang="c++"> #include <QCoreApplication> #include <QDebug> #include <aws/core/Aws.h> #include <aws/dynamodb/DynamoDBClient.h> #include <aws/dynamodb/model/PutItemRequest.h> #include <aws/dynamodb/model/GetItemRequest.h> #include <aws/dynamodb/model/DeleteItemRequest.h> #include <aws/dynamodb/model/UpdateItemRequest.h> #include <aws/dynamodb/model/ScanRequest.h> // ヘルパー関数 Aws::DynamoDB::Model::AttributeValue toAttr(const QVariant& value) { Aws::DynamoDB::Model::AttributeValue attr; if (value.typeId() == QMetaType::QString) attr.SetS(value.toString().toStdString()); else if (value.typeId() == QMetaType::Bool) attr.SetBool(value.toBool()); else attr.SetN(value.toString().toStdString()); return attr; } void printItem(const Aws::Map<Aws::String, Aws::DynamoDB::Model::AttributeValue> &item) { qDebug() << "Item:"; for (const auto& pair : item) { QString key = QString::fromStdString(pair.first); QString value; if (!pair.second.GetS().empty()) value = QString::fromStdString(pair.second.GetS()); else if (!pair.second.GetN().empty()) value = QString::fromStdString(pair.second.GetN()); else if (pair.second.GetBool()) value = "true"; qDebug() << " " << key << ":" << value; } } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Aws::SDKOptions options; Aws::InitAPI(options); { // DynamoDBクライアント作成 (~/.aws/configからリージョンを自動取得) Aws::Client::ClientConfiguration config; // リージョンの指定を削除することで、AWS設定ファイルから自動取得 Aws::DynamoDB::DynamoDBClient client(config); const std::string tableName = "<DynamoDBのテーブル名>"; qDebug() << "=== DynamoDB CRUD Demo ===\n"; // 挿入 : PutItem qDebug() << "### 1. Insert Item ###"; Aws::DynamoDB::Model::PutItemRequest putReq; putReq.SetTableName(tableName); putReq.AddItem("id", toAttr(1)); putReq.AddItem("name", toAttr("Taro Yamada")); putReq.AddItem("age", toAttr(30)); putReq.AddItem("email", toAttr("taro@example.com")); if (client.PutItem(putReq).IsSuccess()) qDebug() << "✓ Item inserted"; // 取得 : GetItem qDebug() << "\n### 2. Get Item ###"; Aws::DynamoDB::Model::GetItemRequest getReq; getReq.SetTableName(tableName); getReq.AddKey("id", toAttr(1)); auto getResult = client.GetItem(getReq); if (getResult.IsSuccess()) printItem(getResult.GetResult().GetItem()); // 更新 : UpdateItem qDebug() << "\n### 3. Update Item ###"; Aws::DynamoDB::Model::UpdateItemRequest updateReq; updateReq.SetTableName(tableName); updateReq.AddKey("id", toAttr(1)); updateReq.SetUpdateExpression("SET age = :val, email = :email"); updateReq.AddExpressionAttributeValues(":val", toAttr(31)); updateReq.AddExpressionAttributeValues(":email", toAttr("taro.new@example.com")); if (client.UpdateItem(updateReq).IsSuccess()) { qDebug() << "✓ Item updated"; printItem(client.GetItem(getReq).GetResult().GetItem()); } // 全件取得 : Scan qDebug() << "\n### 4. Scan Table ###"; Aws::DynamoDB::Model::ScanRequest scanReq; scanReq.SetTableName(tableName); auto scanResult = client.Scan(scanReq); if (scanResult.IsSuccess()) { qDebug() << "Found" << scanResult.GetResult().GetItems().size() << "items"; for (const auto& item : scanResult.GetResult().GetItems()) printItem(item); } // 削除 : DeleteItem qDebug() << "\n### 5. Delete Item ###"; Aws::DynamoDB::Model::DeleteItemRequest delReq; delReq.SetTableName(tableName); delReq.AddKey("id", toAttr(1)); if (client.DeleteItem(delReq).IsSuccess()) qDebug() << "✓ Item deleted"; } Aws::ShutdownAPI(options); return 0; } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Qt]]
Qtの応用 - AWS DynamoDB
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse