mongoDBをrubyからmongo使う(mongo-acriverecord-ruby)

mongo-acriverecord-rubyを使うと、mongoDBでactiverecordチックにアクセスできる。
http://github.com/mongodb/mongo-activerecord-ruby:mongo-activerecord-ruby

本当のactiverecordから使うならhttp://github.com/mongodb/activerecord-mongo-adapter:activerecord-mongo-adapterがいいみたいです。

せっかくのドキュメント指向なのにRDB風に使うのはどうなの?とか思いますが。

インストール

前提としてhttp://d.hatena.ne.jp/amacou/20091205/1260035177:昨日の作業はやっていて、デーモンも上がっている状態です。

gemcutterすでにインストールしてるなら以下は省略。

$ sudo gem install gemcutter
$ sudo gem tumble

でインストール

$ sudo gem install mongo_record

使ってみる

では、ありがちなblogっぽいDBの操作をやってみます。
まずはPostクラスを作ります。

#post.rb
require "mongo"
require "mongo_record"
require File.join(File.dirname(__FILE__), 'comment')

class Post < MongoRecord::Base
  collection_name :posts
  fields :title, :content
  has_many :comments, :class_name => "Comment"

  def to_s
    "title: #{self.title} content: #{self.content}"
  end

end

つぎにCommentクラスを作ります。

#comment.rb
require "mongo"
require "mongo_record"

class Comment < MongoRecord::Base
  collection_name :comments
  fields :name, :content

  belongs_to :post
  def to_s
    "name: #{self.name}, content: #{self.content}"
  end
end

上記を使うMainファイルを作ります。

#blog.rb
# -*- coding: utf-8 -*-
require "mongo"
require "mongo_record"
require File.join(File.dirname(__FILE__), 'post')
require File.join(File.dirname(__FILE__), 'comment')

MongoRecord::Base.connection = Mongo::Connection.new.db('blog')

#とりあえず空にしとく
Post.destroy_all
Comment.destroy_all

def show
  puts ""
  puts "=" * 50
  Post.find(:all).each do |pos|
    puts "日記"
    puts "  #{pos}"
    pos.comments.each do |com|
      puts "   コメント"
      puts "     #{com}"
    end
  end
  puts "=" * 50
  puts ""
end


puts "日記をつける"

post = Post.new(:title => "うんこ", :content => "きょうはおおきなうんこがでた" )
post.save

show

puts "コメントをつける(belogs_to を利用)"
comment = Comment.new(:name => "通りすがりさん", :content => "わたしもおおきなうんこでした", :post => post)
comment.save


show

puts "コメントをつける2( << を利用)"
comment2 = Comment.create(:name => "通りすがりさん", :content => "わたしはコロコロのうんこでした")
post.comments << comment2
post.save

show

puts "自作自演日記をつける"
comment3 = Comment.create(:name => "自作自演さん", :content => "まだだしちゃだめ")
post2 = Post.new(:title => "うんこ", :content => "でそう", :date => Date.new, :comments => comment )
post2.save

show

で実行

$ ruby blog.rb
日記をつける

==================================================
日記
  title: うんこ content: きょうはおおきなうんこがでた
==================================================

コメントをつける(belogs_to を利用)

==================================================
日記
  title: うんこ content: きょうはおおきなうんこがでた
==================================================

コメントをつける2( << を利用)

==================================================
日記
  title: うんこ content: きょうはおおきなうんこがでた
   コメント
     name: 通りすがりさん, content: わたしはコロコロのうんこでした
==================================================

自作自演日記をつける

==================================================
日記
  title: うんこ content: きょうはおおきなうんこがでた
   コメント
     name: 通りすがりさん, content: わたしはコロコロのうんこでした
日記
  title: うんこ content: でそう
   コメント
     name: 通りすがりさん, content: わたしもおおきなうんこでした
==================================================

ソース見てみたら、belongs_toはまだ実装されていないみたいです。
でもhas_manyとか関連はちゃんと動いています。

実データはどうなっているのか確認。
mongoコマンドでインタラクティブにDBを操作できます。

$ mongo 
MongoDB shell version: 1.1.4
url: test
connecting to: test
type "help" for help
> use blog
switched to db blog
> show collections
comments
posts
system.indexes
> db.posts.find()
{ "_id" : ObjectId("4b1bcc000b965d203b000001"), "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "comments" : [ { "$ref" : "comments", "$id" : ObjectId("4b1bcc000b965d203b000003") } ], "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "title" : "うんこ", "updated_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "_ns" : "posts", "updated_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "content" : "きょうはおおきなうんこがでた" }
{ "_id" : ObjectId("4b1bcc000b965d203b000005"), "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "comments" : [ { "$ref" : "comments", "$id" : ObjectId("4b1bcc000b965d203b000002") } ], "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "title" : "うんこ", "updated_at" : null, "_ns" : "posts", "updated_on" : null, "date" : /(?:)/, "content" : "でそう" }

commentsの中に配列で関連するcommentのIDを保存している。
ちなみにcommentsは以下のようになってました。

> db.comments.find()
{ "_id" : ObjectId("4b1bcc000b965d203b000002"), "name" : "通りすがりさん", "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "post" : { "$ref" : "posts", "$id" : ObjectId("4b1bcc000b965d203b000001") }, "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "_ns" : "comments", "content" : "わたしもおおきなうんこでした" }
{ "_id" : ObjectId("4b1bcc000b965d203b000003"), "name" : "通りすがりさん", "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "_ns" : "comments", "content" : "わたしはコロコロのうんこでした" }
{ "_id" : ObjectId("4b1bcc000b965d203b000004"), "name" : "自作自演さん", "created_at" : "Mon Dec 07 2009 00:21:36 GMT+0900 (JST)", "created_on" : "Mon Dec 07 2009 00:00:00 GMT+0900 (JST)", "_ns" : "comments", "content" : "まだだしちゃだめ" }

ドキュメント指向ってちゃんと勉強していないけど、上記のようなデータだと、postもcommentも同じコレクションにしちゃった方がいいのかな?

ちゃんとドキュメント指向を勉強してみたいです。
(参考になるサイトや参考書をご存知のかたは教えてください。)