桐株式会社の開発者ブログ

レガシーな不動産建築業界をITの力で変えたい

DynamoDBのORマッパーのDynamoidの使い方(導入編)

はじめに

こんにちは。rsoooです。

前回はいきなりネタシェルコマンドを解説してしまったので、 今回はもうちょっと現在開発で使用している、Ruby on Railsに関連した内容をお話しようと思います。

現在開発しているコンタクトセンターサービス ナオシテというシステムで、新たにAWSDynamoDBの使用を始めましたので、そのORマッパーとして知られるgemのDynamoidを使用してみましたので、その内容と導入手順を簡単にご紹介します。

DynamoDBとは

説明するまでもないかもですが、AWSの提供するスキーマレスのフルマネージドデータベースサービスです。いわゆるKey-Value型のデータベースに分類されますが、ざっくり言うと、こちらが要求したいアクセス性能を指定してやれば、AWSでそれを満たすようによろしく分散してくれるので、簡単に構築、管理できると謳われています。

なぜDynamoDBを使用したか

弊社の構築しているコンタクトセンターサービス ナオシテは、設備の修繕に関するトランザクションを履歴としてすべて記録したいという要件がありました。それらのトランザクションは、大量に発生し、今後どのような項目が発生するか現時点で確定しきれないので、 とりあえず大量のトランザクションを受け切れるスキーマレスのデータベースが必要と判断しました。またナオシテはAWS上で構築されているので、親和性の高いスキーマレスのデータベースとして、DynamoDBを選択しました。*1

Dynamoidとは

Rubyアプリケーション上で動作する、DynamoDBのORマッパーです。AcitiveRecordと似たような感覚でモデルを定義してやれば、そのモデルに対するデータの読み書きを、DynamoDBのアクセスに変換してくれる機能を持っています。DynamoDBのアクセスは内部で AWS SDK(ver2) を使用しています。githubを見る限り、開発は頻繁と言わないまでも継続的に続いているようです。

DynamoDB導入

それでは、DynamoDBの使用した簡単な操作をご紹介します。

今回は、以下のバージョンで動かしております。

$cat /etc/issue
Ubuntu 14.04.5 LTS \n \l
$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
$ rails -v
Rails 5.0.0

導入

まずはじめに、AWS CLIをまだ入れてない人は、 CLIを入れましょう。DynamoDBのテーブル作成や、デバッグに必要になります。

公式にもありますが、pipが入っていれば、以下のコマンドを叩けばインストールできます。

 $ pip install --upgrade --user awscli

CLIがインストールされたaws configure でアクセスキーの設定をすれば完了です。

次に、DynamoDBをローカルで動かすための開発環境を入れます。これをダウンロードして好きな場所に展開して、以下のコマンドで実行できます。 # javaで動かすので、javaが入っていない方はjavaを入れましょう

 $ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar

デフォルトで8000番ポートでDynamoDBが起動します。ちゃんと起動しているか確認するために、以下のコマンドで接続確認します。

$ aws dynamodb list-tables --endpoint-url http://localhost:8000
{
    "TableNames": [
    ]
}

まだテーブルを作成していないので、何も表示されないですが、上記のような応答が帰って来れば正常に起動できていることが確認できます。

Rails側の準備

それではDynamoidの設定をしていきましょう。 と言っても、公式にあるようにGemfileに以下を追記してbundle installすれば終わりです。Gemさん便利ですね。

 # Gemfileに追記
 gem 'dynamoid', '~> 1'
 gem 'aws-sdk', '~>2'

 $ bundle install

config/initilizer/aws.rb に設定を追記します。細かい説明は割愛しますが、以下のようにアクセスキーと設定値を入れてやれば大丈夫です。

Aws.config.update({
      region: 'ap-northeast-1',
      credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'])
})

  Dynamoid.configure do |config|
      config.adapter = 'aws_sdk_v2' 
      config.namespace = nil
      config.warn_on_scan = true
      config.read_capacity = 5
      config.write_capacity = 5
      config.endpoint = 'http://localhost:8000'
  end

今回はローカルのDdynamoDBを使用しているので、エンドポイントはそれを指定しています。また、namespaceを使用するとDynamoDBにアクセスする際にテーブル名に自動的にnamespaceを付与してくれます。これはDynamoidからアクセスする際にはわかりやすいのですが、それ以外のシステムからテーブルを作成したりする場合などは、かえって不便になるので、今回はnilにしました。

また、ここで指定するAWSのアクセスキーは、aws configure で指定したアクセスキーと同じものを使用してください。DynamoDBローカルは、アクセスキーごとにデータの保存先が異なるので、ここが違うとCLIからデータの確認ができません。

ここまでで、準備完了です。

モデルの作成

それでは、いよいよDynamoDBにアクセスするモデルを作っていきましょう。

すごい雑な例ですが、サンプルとしてBookモデルを作成してみます。

class Book
  include Dynamoid::Document

  table :name => "book_table", :key => :book_id

  field :title
  field :isbn

end

Dynamoid::Document をincludeしてやれば、DynamoDBとアクセスするモデルとして使用できます。DynamoDBのキーの指定は、HASHキーのみか、HASHキーとRANGEキーの複合キーのどちらかが選択できるのですが、今回はHASHキーのみを使用しています。

また、DynamoDBで扱いたいカラムをfieldとして定義します。 DynamoDBはスキーマレスなので、テーブル名とキー(この場合HASHキーのみ)を決めてやれば、後のフィールドは好き勝手に指定しても、よろしくDynamoDBは保存してくれます。

Railコンソールを使って、試しにデータを保存してみます。

$ bundle exec rails c
> book = Book.new
=> #<Book:0x007fc9c54935b8
> book.book_id = "id111" #idは適当に決める
=> "id111"
> book.title = "Effective Ruby" #fieldを決める
=> "Effective Ruby"
> book.isbn = "123456789"
=> "123456789"
> book.save

(459.47 ms) LIST TABLES - [[]]
(459.93 ms) CACHE TABLES
(102.64 ms) CREATE TABLE
(108.19 ms) PUT ITEM … 
>

これで保存完了しました。テーブルが存在しない場合、作成もやってくれます。 ちゃんと保存されたか、AWS CLIで確かめます。

# 表示を見やすくするため、jqを使用しています
 $ aws dynamodb list-tables --endpoint-url http://localhost:8000 | jq .TableNames 
[
  "book_table",
]

テーブルが作成されていることが確認できました。中身を見るために、全件スキャンを行います。

 $ aws dynamodb scan --endpoint-url http://localhost:8000 --table-name book_table | jq .Items
[
  {
    "title": {
      "S": "Effective Ruby"
    },
    "book_id": {
      "S": "id111"
    },
    "updated_at": {
      "N": "1497963748.3617456"
    },
    "isbn": {
      "S": "123456789"
    },
    "created_at": {
      "N": "1497963748.3612344"
    }
  }
]

DynamoDBに保存されていることが確認できました!

終わりに

いかがでしたでしょうか。DynamoDBのインデックスの扱い方や、Dynamoidのgemがどのように動いているかを説明しようと思ったのですが、長くなってきたので、それはまた次回にしようと思います。

記載している内容に間違い、指摘などございましたら、コメント欄に追記いただけると幸いです。

桐株式会社ではエンジニアを募集中!

桐株式会社ではレガシーな不動産建築業界をITの力で変えたいエンジニアを募集しております! まずはランチなどでお話しませんか?お気軽にお問い合わせください。

*1:ただ単に使ってみたかったという気持ちも半分ぐらいありますが