NoSQLデータベースを試してみる

第4回 スキーマレスで柔軟に扱えるMongoDB

この記事を読むのに必要な時間:およそ 4 分

RailsからMongoDBを利用してみる

今回はMongoMapperというライブラリを使ってRubyからMongoDBを操作します。これはActiveRecordライクにMongoDBを扱えるライブラリです。必要に応じてインストールしてください。

mongo_mapperのインストール

gem install mongo_mapper

まず,MongoDBで扱いたいモデルで設定を行う必要があります。最低限やることはMongoMapper::Documentをインクルードすることだけです。今回の例ではageとinterestの2つをキーとして設定していますが,これは必須ではありません。ただし,このようにキーとして指定することで,以下のようなメリットがあります。

  • 文字列以外の型を指定できる(IntegerやArray,Booleanなど)
  • データ作成時や更新時にvalidationを行うことができる

MongoDBを利用したモデルのコード例

class User
  include MongoMapper::Document

  key :age, Integer, :default => 0
  key :interest, Array
end

さらにコントローラー側は以下のようになります。開発時はloggerを指定して,どんなクエリが実行されているのかを見れるようにした方が良いでしょう。

MongoDBを利用したコントローラーのコード例

class MongodbController < ApplicationController
  require 'mongo_mapper'
  MongoMapper.connection = Mongo::Connection.new("localhost", 27017, :logger => Logger.new(STDOUT))
  MongoMapper::database = 'test'

  def set
    User.create(:name => "太郎1")
    User.create(:name => "太郎2", :age => 20)
    User.create(:name => "太郎3", :interest => %w!soccer baseball tennis!)
    User.create(:name => "太郎4", :interest => %w!soccer!)
  end

  def get
    p User.all(:name => /太郎/)                             # 太郎1, 太郎2, 太郎3, 太郎4
    p User.all(:age => 20)                                 # 太郎2

    # interestにsoccerを含んでいるデータ
    p User.all(:interest => “soccer”)                      # 太郎3, 太郎4
                                                                
    # interestにsoccerもしくはtennisのいづれかを含んでいるデータ
    p User.all(:interest => %w!soccer tennis!)             # 太郎3, 太郎4

    # interestにsoccerとtennisを両方とも含んでいるデータ
    p User.all(:interest => {"$all" => %w!soccer tennis!}) # 太郎4
  end
end

Array型の扱いは若干わかりにくいかもしれません。Array型のカラムに対して配列を渡して検索した場合,デフォルトでは「いずれかを含む」の意味で解釈されます。渡した配列を全て含んでいるデータが欲しければ,$allというキーワードを指定しなくてはいけないことに注意してください。

便利なメソッド

その他にも様々な便利メソッドがあります。例えばadd_to_setというメソッドを利用すると,⁠対象の配列の中にそのデータが存在しなければ追加し,存在していれば何もしない」という処理を簡単に行うことができます。

MongoDBの便利なメソッド

def add_to_set
  p User.first(:name => "太郎4") # interest: ["soccer"]
  
  User.add_to_set({:name => "太郎4"}, :interest => "tennis")
  p User.first(:name => "太郎4") # interest: ["soccer", "tennis"]
  
  User.add_to_set({:name => "太郎4"}, :interest => "soccer")
  p User.first(:name => "太郎4") # interest: ["soccer", "tennis"]
end

まとめ

MongoDBはshardingさせられるため,スケーラビリティに優れたデータベースです。さらに,データ型として配列が扱えたり,検索が柔軟に行えたりするため,様々な場面で使えるのではないでしょうか。また,データベース側とアプリ側でスキーマの整合性を気にする必要がないのも大きなメリットだと思います。

著者プロフィール

佐々木達也(ささきたつや)

普段は主にHadoopを用いた大規模データ解析を行っている象使いエンジニア。最近はNoSQLデータベースにも興味を持っている。Ruby, Railsはもちろん、広島カープも大好き。

bloghttp://blog.livedoor.jp/sasata299/

twitterhttp://twitter.com/sasata299/