AWS DynamoDBをAWS SDK for Javaから使ってみる(低レベルAPI編)

この記事は2012年に書かれたものです。最新情報はAWS公式ドキュメントを参照してください。

DynamoDB が東京リージョンで使えるようになりましたね!ようこそ東京リージョンへ!

さて、今日は米国東海岸リージョンでAWS Toolkit for Eclipseを使ってDynamoDBの低レベルAPIを使ってみたメモを載せます。

事前準備

  • Eclipseをインストール
  • AWS Toolkit for Eclipseをインストール&セットアップ
    • 詳細: http://aws.amazon.com/jp/eclipse/
    • リリースノート: http://aws.amazon.com/releasenotes/Java?browse=1
    • AWS SDK for Java, AWS Explorerなど各種便利機能がたくさん入っています。
    • インストール後にはAccessKeyやSecretKeyを設定し、正しく動作することを確認しておきます。動作確認を兼ねてAWS Exploerを触ってみたり、付属しているサンプルアプリを動かしてみたりすると良いです。
    • AWS ExplorerでDynamoDBにアクセスするときはリージョンが正しく指定されているか確認してください。
  • AWS DynamoDBにサインアップ
    • AWSマネジメントコンソールからサインアップできます。
EclipseAWS ExplorerDynamoDBのテーブルを表示させた様子


参考

概要

DynamoDBはフルマネージドのNoSQLサービスで、高い信頼性、データ耐久性を備えています。データ容量が無制限、アクセス性能をコントロールできるといった特徴があります。その他、詳しい機能はAWS WebサイトやAWSブログで紹介されています。

DynamoDBでは、データベースはテーブルの集まりでできています。それぞれのテーブルはアイテムの集まりで、アイテムは属性の集まりです。リレーショナルデータベースでは、テーブルはテーブル名、プライマリキー、カラム名のリスト、データの型などあらかじめ定義されたスキーマを持っていますが、DynamoDBのテーブルはスキーマレスです。各アイテムはアイテムのサイズが64KB以下であればいくつでも属性を持つことができます。アイテムのサイズは属性名と値の長さを合計で計算されます。

APIについて

AWS SDK for JavaではDynamoDBを操作するためのAPIとして低レベルAPIと高レベルAPIが用意されています。

  • 低レベルAPI(protocol-level API)
    • テーブルの作成・更新・削除、アイテムの作成・更新・読み込み・削除、クエリ、スキャンといったすべての動作を行うことができます。ただし、いろいろなことができる反面、細かくプログラミングする必要があります。
  • 高レベルAPI
    • JavaのObjectとDynamoDBのデータをマッピングしてくれて、オブジェクトの永続化に利用できます。高レベルAPIではテーブルの作成・更新・削除はできませんが、既存のコードベースがある場合には便利に使えます。

参考

低レベルAPIを使ってみる(テーブル作成〜プライマリキーでの検索)

Dynamo DBユーザガイドにあるGetting Startedでは低レベルAPIを使ったテーブル作成〜プライマリキーでの検索までが掲載されています。ではGetting Startedに沿って使ってみましょう。

テーブルを作成

マネジメントコンソールからテーブルを作ります。Getting Startedでは2つのユースケースが紹介されており、それぞれ以下のようなテーブルを作成します。プライマリキーや設定するスループットはGetting Startedに掲載されている表の内容に沿って入力します。ページの下の方にはマネジメントコンソールのスナップショットもあるので参考に。

Use case 1: 書籍情報向けデータベース
書籍の情報を管理するためのデータベースです。書籍のタイトル、著者、ISBNなどのデータがあります。

  • ProductCatalog

Use case 2: オンラインフォーラム向けデータベース
AWS Forumのようなオンラインフォーラムのためのデータベースです。Forum>Thread>Replyという親子関係があり、各タイトル、書き込み内容、日付などのデータが保存されています。

  • Forum
  • Thread
  • Reply
サンプルデータを投入

まず、Eclipseで新規AWSプロジェクトを作成します。続いて、Getting Startedに掲載されているサンプルプログラムをコピー&ペーストして実行すると各テーブルにサンプルデータが書きこまれます。このサンプルプログラムは低レベルAPIで書かれています。

EclipseでのAWSプロジェクトの作り方はこちら。

プライマリキーで検索(Query)してみる

プライマリキーで検索する処理をQueryと呼びます。一方、プライマリキー以外を使ってテーブル全体を検索する場合はScanと呼ばれます。Scanについては後ほど。

一般的に、Queryの方が効率的に検索できます。ドキュメントによると、Queryの性能は検索によって取得されるデータの量に依存し、Scanはテーブルが大きくなった時に処理速度が落ちます。

こちらもGetting Startedのサンプルコードをコピー&ペーストすれば動作確認できます。

  • Use case 1 "Product Catalog"のデータをプライマリキー(シンプルハッシュキー)を指定して検索
    • 任意のPrpduct IDを指定して検索を行います。
    • サンプルコードでは、GetItemRequest クラスを使って指定されたプライマリキーのデータを取得しています。
    private static void getBook(String id, String tableName) {
        
            // テーブル名、プライマリキー、取得する属性を指定してデータを取得
            GetItemRequest getItemRequest = new GetItemRequest()
                .withTableName(tableName)
                .withKey(new Key()
                    .withHashKeyElement(new AttributeValue().withN(id)))
                .withAttributesToGet(Arrays.asList("Id", "ISBN", "Title", "Authors"));
            
            GetItemResult result = client.getItem(getItemRequest);

            // Check the response.
            System.out.println("Printing item after retrieving it....");
            printItem(result.getItem());            
    }
 
 // ソースコードはGetting Startedより抜粋
 // http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/GettingStartedJavaQuery.html
  • Use case 2 "Reply"のデータからプライマリキー(コンポジットプライマリキー)のレンジ属性を指定して検索
    • Replyテーブルはコンポジットプライマリキーキーが使われていて、"ReplyDateTime"はレンジ属性として設定されています。そのため、日付を範囲指定してデータを取得することができます。
    private static void findRepliesInLast15DaysWithConfig(String tableName, String forumName, String threadSubject) {

        String replyId = forumName + "#" + threadSubject;

        long twoWeeksAgoMilli = (new Date()).getTime() - (15L*24L*60L*60L*1000L);
        Date twoWeeksAgo = new Date();
        twoWeeksAgo.setTime(twoWeeksAgoMilli);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        String twoWeeksAgoStr = df.format(twoWeeksAgo);
        
        Key lastKeyEvaluated = null;
        do {
        	
         //検索条件を指定
           //プライマリキーのレンジ属性を2週間前の日付と比較する。
           //比較演算子にはGT : Greater thanを使用
            Condition rangeKeyCondition = new Condition()
            .withComparisonOperator(ComparisonOperator.GT.toString())   
            .withAttributeValueList(new AttributeValue().withS(twoWeeksAgoStr));
            
            //検索リクエストを作る
            //テーブル名、プライマリキーを指定して検索条件で絞込みし、
            //これまでのループで取得したものを除いて1件だけ取得する。
            //検索結果の属性のうち、"Message", "ReplyDateTime", "PostedBy"を取得する。
            QueryRequest queryRequest = new QueryRequest().withTableName(tableName)
            .withHashKeyValue(new AttributeValue().withS(replyId))
            .withRangeKeyCondition(rangeKeyCondition)
            .withAttributesToGet(Arrays.asList("Message", "ReplyDateTime", "PostedBy"))
            .withLimit(1).withExclusiveStartKey(lastKeyEvaluated);   
            
            //検索を実行し、結果を出力
           QueryResult result = client.query(queryRequest);
            for (Map<String, AttributeValue> item : result.getItems()) {
                printItem(item);
            }
            //このループで取得したプライマリキーを記録
            //result.getLastEvaluatedKey()=null となった場合は、検索結果をすべて取得し終わったことを意味する。
            lastKeyEvaluated = result.getLastEvaluatedKey();

        } while (lastKeyEvaluated != null);        
    }
 // ソースコードはGetting Startedより抜粋
 // http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/GettingStartedJavaQuery.html

Queryで使える比較演算子など、詳細については以下のURLに掲載されています。

まとめ

AWS Toolkit for EclipseからDynamoDBを動かしてみるのは意外と簡単です。ぜひ試してみてください。

今回は低レベルAPIを使う方法を紹介しましたが、近いうちに高レベルAPIを使う方法もエントリにまとめたいと思います。