Railsで複数のMySQLとMongoDBに接続する方法

f:id:boost-up:20171205233557j:plain

RailsでWebアプリケーションを開発しているときに、MySQLとMongoDBそれぞれで複数のデータソースに接続したくなって調べた時のメモです。

なお、モデルとデータベースとの関連付けはMySQL(Active Record)を主、MongoDB(mongoid)を複としています。

必要な設定

MySQLとMongoDBでは設定方法が少し異なりますが、基本的な考え方は一緒です。

変更するのはそれぞれ以下の2点です

  1. configファイルへの接続情報の追加
  2. 対象Modelの接続情報の変更

以降では、各データベースについて、デフォルトの接続先をprimary、2つ目の接続先をsecondaryと表記します。 secondaryに対応するModelをそれぞれMysqlSecondary、MongodbSecondaryと表記します。 今回はdevelopment環境を前提に説明しますが、productionでも基本的に同じです。

MySQLで2つ目のデータベースにつなぐ場合の設定

configファイルへの接続情報の追加

config/database.ymlを開いて次のようにdevelopment2を追加してください。 データベース名は何でも良いのですが、後でModel側からRails.envで環境名で取れるように元のdevelopmentに文字列を付加した形が良いと思います。

development:
  adapter: mysql2
  database: primary
  socket: /var/lib/mysql/mysql.sock
  encoding: utf8
  username: primary_database_username
  password: primary_database_password

development2:
  adapter: mysql2
  database: secondary
  socket: /var/lib/mysql/mysql.sock
  encoding: utf8
  username: secondary_database_username
  password: secondary_database_password

ここまででMySQLについて、configファイルへの接続情報の追加が完了しました。

対象Modelの接続情報の変更

app/model/mysql_secondary.rbを開いて、次のように「establish_connection」を追加してください。

class MysqlSecondary < ActiveRecord::Base
  establish_connection("#{Rails.env}2")
end

たったこれだけで、MysqlSecondaryはsecondaryを見に行くようになります。

念のため補足しますと、MysqlSecondaryモデルを作る際にmigrationファイルを生成している場合はschemaの整合性を保つためにrake db:migrateを実行し、primaryの方にテーブルを作っておかないとアプリケーション起動後にエラーが表示されると思います。 出来ればMysqlSeondaryについては最初からmigrationファイルを作らないことをお勧めします。

ここまででMysqlSecondaryについての設定は完了です。

MongoDBで2つ目のデータベースに接続する場合の設定

configファイルへの接続情報の追加

config/mongoid.ymlを開いて、次のように「hoge」以下を追加してください。 こちらはMySQLの場合と違い、development環境の設定の子要素として定義するので接続識別子(hoge)は何でも大丈夫です。

development:
  clients:
    default:
      database: primary
      hosts:
        - localhost:27017
    hoge:
      database: secondary
      hosts:
        - localhost:27017

ここまででMongoDBについて、configファイルへの接続情報の追加が完了しました。

対象Modelの接続情報の変更

app/model/mongodb_secondary.rbを開いて、次のよう「store_in」の1行を追加してください。

class MongodbSecondary
  include Mongoid::Document
  store_in collection: "mongodb_secondaries", client: "hoge"
end

こちらもたったこれだけです。 これで、MongodbSecondaryもsecondaryを見に行くようになりました。

我流、MySQLとMongoDBの使い分けポリシー

多少の例外はありますが、基本的に以下のいずれかに該当すればMySQL、それ以外はMongoDBを使うようにしてます。

  1. マスター
  2. 複数テーブルのjoinが必要な場合
  3. アプリケーションで処理した集計結果(集計元はMongoDBである場合もあります)
  4. トランザクション管理が必要な場合

昔はNoSQLでは出来なかった事が出来るようになったり(得意かどうかはまた別)、RDBも性能面でのボトルネックが改善されたり、データベース製品はまだ進化してますし、KVSやカラムDB、分散ファイルシステムなど、データを保存する選択肢は他にも色々あります。

上記はあくまで現時点でMySQLとMongoDBの使い分けを考えた場合の私なりの結論です。

「知らないと言うことは幸せであるが、それ以上に可哀想である。」