初めての MongoDB
MongoDB が気になったのでちょっと試してみた。なぜ MongoDB が気になったのかというと、Heroku の Add-ons で MongoHQ が使えるということなので。
Heroku 上で動作させることを前提としているので、言語は Ruby を使用。http://www.mongodb.org/display/DOCS/Object+Mappers+for+Ruby+and+MongoDB にOマッパー*1のリストがある。MongoRecord というのが MongoDB の開発元(?) である 10gen が開発しているようなので、それを使ってみることにした。
インスートル
...忘れた。パッケージで入れたのは覚えてる。
レコードの作成と検索
コード
require 'rubygems' require 'mongo' require 'mongo_record' class User < MongoRecord::Base collection_name :users fields :name, :age, :sex #index :name # なぜかエラーになるのでコメント def to_s "name:[#{name}], age:[#{age}], sex:[#{sex}]" end end MongoRecord::Base.connection = Mongo::Connection.new.db('mydb') #---- 作成 users = [] users << User.new(:name => 'foo', :age => 16, :sex => :male) users << User.new(:name => 'foo', :age => 32, :sex => :female) users << User.new(:name => 'bar', :age => 64, :sex => :female) users << User.new(:name => 'hoge', :age => 128, :sex => :male) users.each {|u| u.save} #---- 検索 puts '---- all' User.find(:all).each {|u| puts u.to_s} puts '---- name = "foo"' User.find(:all, :conditions => ['name = ?', 'foo']).each {|u| puts u.to_s} puts '---- name = "foo" and age < 32' User.find(:all, :conditions => ['name = ? and age < ?', 'foo', 32]).each {|u| puts u.to_s} puts '---- select' puts User.find(:last, :select => [:name, :age]).to_s puts '---- not found :by all' p User.find(:all, :conditions => ['name = ?', 'pero']) puts '---- not found by :last' users.each {|u| u.delete} p User.find(:last)
結果
---- all name:[foo], age:[16], sex:[male] name:[foo], age:[32], sex:[female] name:[bar], age:[64], sex:[female] name:[hoge], age:[128], sex:[male] ---- name = "foo" name:[foo], age:[16], sex:[male] name:[foo], age:[32], sex:[female] ---- name = "foo" and age < 32 name:[foo], age:[16], sex:[male] ---- select name:[hoge], age:[128], sex:[] ---- not found :by all #<Mongo::Cursor:0xb74469a40 ...> # 長いので省略 ---- not found by :last nil
- find の第一引数には id, :all, :first, :last を指定する。
- :all と :first, :last で返ってくるオブジェクトが違う。:all だと Mongo::Cursor が返ってくるけど、:first, :last の場合は User オブジェクトが返ってくる。統一されていた方がいいような。...そうでもないか、あらかじめ多くて 1 件しかレコードが返ってこないことはわかってるから。
- 条件文に "?" をプレースホルダとして使ったけど、(No)SQLインジェクション対策はされるのだろうか?
- そもそも、どうなるとインジェクションされるのだろう*2?
- いろいろな NoSQL サーバがあるけど、脆弱性対策をなくすためこれをしとけっていうのは各サーバごとに異なる?
- save メソッドは commit とは違うものだった。delete したあとで save を実行するとレコードが再度書き込まれた...orz。
# save しないと DB には反映されないだろうと思っていたが、そんなことはなかった。 # ↓消して書き込んでいるので無意味な処理。 users.each {|u| u.delete; u.save }