RubyでMySQL,MongoDB,Neo4jを共存させて用途に合わせて使い分ける。


## こんな人におすすめ
- railsアプリケーションをMySQLで利用している。
- 用途に応じてNoSQLやGraphDBも利用したい。
- でもMySQLをやめて完全に移行するのは都合が悪い。

## なぜこんなことをしたくなったのか？
- 大量のグラフデータを扱う上でMySQL(RDB)でさばくのに無理が生じてきた
- 大規模なログ取得＆分析ができる仕組みまではいらないけど、さくっとログ取得と分析がしたい


## 実際にやったこと
- MySQLで動いているrailsアプリケーションにNoSQLとGraphDBも使えるようにする。
※今回は、NoSQLはMongoDB、GraphDBはneo4jを利用しました。

## ①MongoDBをMySQLと共存して動くようにしてみる

rubyでMongoDBを利用できるmongoidというgemを入れます。

```ruby:Gemfile
gem 'mongoid', '~> 5.0.0'
```

```ruby:config/application.rb
#以下のどちらかの設定を記載

#model生成時にデフォルトでactive_record(mysql)にしたい場合
config.generators do |g|
  g.orm :active_record
end

#model生成時にデフォルトでMongoDBにしたい場合
config.generators do |g|
  g.orm :mongoid
end
```

```ruby:config/mongoid.yml
development:
  clients:
    default:
      database: "database_name"
      hosts:
        - "domain":"port"
      # The name of the user for authentication.
      user: "username"

      # The password of the user for authentication.
      password: "password"
```

```ruby:console
rails g model mysql_model name:string age:integer #active_recordを使ってmodelが生成される
rails g mongoid:model mongo_model name:string age:integer #mongoidを使ってmodelが生成される
```

mongoidを使って生成されたmodelは以下のようになります。

mongoidを使ったmodelの場合migrationファイルは生成されずmigrationをかけずともactive_recordで生成したmodelと近い形で利用することができます。

```ruby:app/models/mongo_model.rb
class MysqlModel
  include Mongoid::Document
  field :name, type: String
  field :age, type: Integer
end
```

実際にconsoleを立ち上げてmodelを叩いてみると、

```ruby:console
MongoModel.new
=> #<MongoModel _id: 565e81bed23812485f000001, name: nil, age: nil>

MongoModel.create(name: "Toshiyuki Oka", age: 31)
=> #<MongoModel _id: 565e81bed23812485f000002, name: "Toshiyuki Oka", age: 31>

MongoModel.first
=> #<MongoModel _id: 565e81bed23812485f000002, name: "Toshiyuki Oka", age: 31>
```

こいつは便利ですね。

## ②Neo4jをMySQLと共存して動くようにしてみる

```ruby:Gemfile
gem 'neo4j', '~> 6.0.0'
```

```ruby:config/application.rb
#mongoのときと同様に以下のどちらかの設定を記載

#model生成時にデフォルトでactive_record(mysql)にしたい場合
config.generators do |g|
  g.orm :active_record
end

#model生成時にデフォルトでNeo4jにしたい場合
config.generators do |g|
  g.orm :neo4j
end
```

```ruby:config/neo4j.yml
development:
  type: server_db
  url: http://localhost:7474
```

```ruby:console
rails g neo4j:model neo4j_model name:string age:integer
```

↑で作ったモデルは以下のようになります。

```ruby:app/models/neo4j_model.rb
class Neo4jModel
  include Neo4j::ActiveNode

  property :name, type: String
  property :age, type: Integer
  index :age  #indexも張れます                                                                                                                                   
end
```

実際にconsoleを立ち上げてmodelを叩いてみると、

```ruby:console
Neo4jModel.new
=> #<Neo4jModel uuid: nil, age: nil, name: nil>

Neo4jModel.create(name: "Toshiyuki Oka", age: 31)
=> CYPHER 97ms CREATE (n:`Neo4jModel` {props}) RETURN ID(n) | {:props=>{:uuid=>"5a54380d-1160-44eb-9680-7757f4bc4a74", :name=>"Toshiyuki Oka", :age=>31}}
=> #<Neo4jModel uuid: "5a54380d-1160-44eb-9680-7757f4bc4a74", age: 31, name: "Toshiyuki Oka">

Neo4jModel.first
=> CYPHER 50ms MATCH (n:`Neo4jModel`) RETURN n ORDER BY n.uuid LIMIT {limit_1} | {:limit_1=>1}
=> #<Neo4jModel uuid: "24caf736-918c-4d60-9e3e-5ec916252919", age: 31, name: "Toshiyuki Oka">

```

こいつも便利ですね！

## 最終的な利用イメージ

- 基本的なアプリケーションのデータベースはRDBで扱う。
- ログ系のデータで色々な分析や効果検証をしたいデータはMongoDBに保存して更新や分析を行う。
- 規模の大きなグラフデータは、neo4jに保存して探索や関係性、距離の問題などを扱う。