hagino3000's blog

平成アーカイブス (更新停止)

Railsでソーシャルブックマーク的なものを作る-その3

つづき。

タグ検索機能の実装

MysqlのFULLTEXT INDEXをそのまま使います。超簡単な全文検索です。一般的には日本語の全文検索では形態素解析かNグラムでテキストの分解を行いますが、最初から分解した形でデータを持つのでその必要がありません。MysqlのFULLTEXT INDEXはフレーズ検索とINDEX更新のパフォーマンスが悪いとWEB+DBPressに書いてありましたが今回はあまり気にしない方向で。そもそもcoreserverMysqlには手を入れられないので打つ手が無いのです、、、。

タグはbookmarksテーブルに半角スペース区切りで持っておきます。カラム名は[delimited_tags]としました。ページ切り替えはpagination_findプラグインを試したかったのでそれを使っています。

初回ページ表示時には全件検索で登録日時の降順にソート、条件入力時にはタグ検索で一致率の高さ降順という仕様にしてみました。そんなコード。


条件入力部の(html.erb)

<% form_tag(:controller=>"top", :action=>"index") do %>
<div id="search_condition">
<div class="label">タグ検索(半角スペース区切りで複数指定可能)</div>
<%= text_field_tag "condition_tags",
	 if @condition_tags.blank? then "" else @condition_tags+" " end ,
	 :class=>"search_condition" %>
<%= submit_tag '再検索' %>
</div>
<% end %>
<%= render :partial=>"page_control" %>


ページコントロール用部分テンプレート(html.erb)

<div width="100%">
<div width="50%" style="float:left">
<%= @bookmarks.size %>件中
<%= @bookmarks.first_item %> - <%= @bookmarks.last_item %>件目
</div>
<div width="50%" style="text-align:right">
<%= link_to("前へ",
		:page=>@bookmarks.previous_page,
		:params=>{ :condition_tags => @condition_tags}) if @bookmarks.previous_page %>
		
<%= paginating_links(@bookmarks,
	:window_size=>2,
 	:always_show_anchors=>true,
	:params=>{ :condition_tags => @condition_tags}) %>

<%= link_to("次へ",
		:page=>@bookmarks.next_page,
		:params=>{ :condition_tags => @condition_tags}) if @bookmarks.next_page %>

</div>
</div>


contoroller

def index
  # receive parameters
  @condition_tags = if params[:condition_tags] then
    params[:condition_tags].strip
  else
    ""
  end
  
  @page = if params[:page] then
    params[:page]
  else
    1
  end
    
  # search
  _page = {:size => 20, :current=>@page}
   
  if @condition_tags.blank? then
    @bookmarks = Bookmark.find(:all,
      :page       => _page,
      :order      => "created_at desc"
    )
  else
    _match  = "match(delimited_tags) against('"+@condition_tags+"') > 4"
    @bookmarks = Bookmark.find(:all,
      :page       => _page,
      :conditions => _match
    )
  end
end

pagination_findプラグインを使っているくらいで、小細工無し。結果の表示は@bookmarksを受け取ってイテレートしてやります。

つづきはこちら
http://d.hatena.ne.jp/hagino_3000/20080412/1208019334