2013年4月7日日曜日

Rails3.2.11+mongoid+elasticsearch(tire)のhas_many, embeds_manyの込み入った実装(1)


まずは通常のhas_many, belongs_toで繋がれた設定とembeds_manyの関係。

前提として、Storeにproductsが紐付いてること。
productを検索ボックスのparams[:q]で検索するという状況で説明する。

mongoidの場合、referenceにあるように、
to_indexed_jsonの中には、self.to_jsonで書くのが一般的。
readmeには以下のように書かれている。


で、このselfには、自動で、全てのfieldをindexes hogeで認識してくれる。
即ち、このproductにembeds_manyされているproduct_additionalsも
自動でincludeしてくれてる。とてもありがたい。
完璧にTireさんに甘やかされてます(∩´∀`)∩


class Product
  include Mongoid::Document
  include Tire::Model::Search
  include Tire::Model::Callbacks
field :product_name, type: String
  field :product_description, type: String
belongs_to :store
embeds_many :product_additionals

  def self.search(params)
    tire.search(load: true) do
      query {string params[:q], default_operator: "AND"} if params[:q].present?
    end
  end
  tire.settings :analysis => {
    :analyzer => {
      :kuromoji => {
        "type" => "kuromoji",
        "tokenizer" => "kuromoji_tokenizer"
      }
    }
  } do
    tire.mapping do
      indexes :description, :analyzer => :kuromoji
      indexes :product_name, :analyzer => :kuromoji, boost: 10
      indexes :store do
        indexes :branch_name, :analyzer => :kuromoji
        indexes :address, :analyzer => :kuromoji
      end
    end
  end
  def to_indexed_json
    self.to_json(include: {store: {only: [:branch_name, :address]}})
  end
end #ここからmodels/store.rb
class Store
include Mongoid::Document
  include Mongoid::MultiParameterAttributes
has_many :products

field :branch_name #支店名
field :address #住所
end

productにとって厄介(has_manyなどの場合の込み入った設定)でないものは簡単にself.to_jsonの後ろにつけてincludeしてしまえばよい。

次回は、storeを検索した場合に、紐付いてるproductとproduct_additionalsをindexをはる方法を書きます。

今日はここまで。