acts_as_searchableをfind並みに使い倒す。

railsでhyperestraierを使うacts_as_searchableを最近弄ってるのでメモ。
インストールとかは省略。こちらが参考になるかも。*1


ドキュメントはここに関数の一覧がある。
そして、検索方法なんかはhyperestraierのユーザーガイド参照する。


複雑な条件式とかできないのかーって色々調べた結果、結構複雑な条件式が使える事がわかったのでメモ。


基本形としてはmodelの定義に

acts_as_searchable :attributes => { :title => nil, :blog => :blog_title }, :searchable_fields => [ :title, :body ]

と書くとドキュメントにあるけど、基本的に全文検索の必要があるカラムをsearchable_fieldsに設定して、
併せて条件を書くカラムを:attributes => { :title, :blog_title}とかすればOK。

acts_as_searchable :attributes => { :title, :blog_title }, :searchable_fields => [ :title, :body ]

別名つけてくれるっぽいけどあまり使ってない。


んで、検索する時は fulltext_search(query = "", options = {}) で検索

  fulltext_search("<span style="font-style:italic;">検索文字列</span>", :attributes => ["<span style="font-style:italic;">attributes query</span>", "<span style="font-style:italic;">attributes query</span>"], options = {})   

と使ってる。


optionsは、実は:attributsも含めてoptionでドキュメントには

* limit - Maximum number of records to retrieve (default: 100)
* offset - Number of records to skip (default: 0)
* order - Hyper Estraier expression to sort the results (example: @title STRA, default: ordering by score)
* attributes - String to append to Hyper Estraier search query
* raw_matches - Returns raw Hyper Estraier documents instead of instantiated AR objects
* find - Options to pass on to the ActiveRecord::Base#find call

とあるんだけどattributesは良く使うのでほとんど必須になった。

raw_matchesは、falseにすると、fulltext_searchの後、find(
all,:conditions => "id IN ( ヒットしたid )")を実行してるようなので、重いのでtrue固定で使ってる。


で、実際の例
例えば、国コード(country_id)が2と一致するデータを検索する場合、
:attributesに

country_id STREQ 2

後、複数の場合として、国コード(country_id)が2と3と4のどれかと一致するデータを検索する場合は
:attributesに

country_id STROREQ 2 3 4

で、かつview_flgがtrueの場合は

view_flg STREQ true


ちなみにここで補足。
trueとか日付とか、全部to_sして格納されてる*2ので、日付とかは
config/enviroment.rbに

ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.update :default => "%Y/%m/%d"

と記述した。


閑話休題、view_flgとcountry_idをチェックした検索はこうなる

SearchDataModel.fulltext_sea^Prch("検索する文字列", :attributes => ["country_id STROREQ 2 3 4", " view_flg STREQ true"])

文字列以外も検索できるので結構複雑な検索文も行けるとかなり嬉しくなってくる。
もちろん事前にmodelでattributes定義しておいてindexが必要な時点で結構面倒だけど。


attributesに使える演算子は以下の通り。

* STREQ : 指定した文字列と一致する。
* STRNE : 指定した文字列と一致しない。
* STRINC : 指定した文字列を含む。
* STRBW : 指定した文字列で始まる。
* STREW : 指定した文字列で終わる。
* STRAND : 指定した文字列の全てのトークンを含む。
* STROR : 指定した文字列の一つ以上のトークンを含む。
* STROREQ : 指定した文字列の一つ以上のトークンと一致する。
* STRRX : 指定した文字列の正規表現に合致する。
* NUMEQ : 数値や日付が指定したものと等しい。
* NUMNE : 数値や日付が指定したものと等しくない。
* NUMGT : 数値や日付が指定したものより大きい。
* NUMGE : 数値や日付が指定したものと同じかより大きい。
* NUMLT : 数値や日付が指定したものより小さい。
* NUMLE : 数値や日付が指定したものと同じかより小さい。
* NUMBT : 数値や日付が指定したものの間である。
hyperestraierのユーザーガイドより抜粋

これで素敵検索ライフ。

*1:アプリケーション作成時に既にインストール済みだったので、自分自身ではインストールしてない為

*2:hyperestraierのrubyライブラリの仕様ぽい