MySQLで全文検索
MySQLで全文検索しようと思い立った。
というのは、自作サイトでタグとコメント欄の全文検索を行いたくなったからだ。
MySQLは日本語の全文検索に対応できていない。
MySQLはバージョン5.0の時点では英文の全文検索にしか対応していない。
日本語で全文検索を行うには、外部ツールの助けが必要になる。
その外部ツールとして senna がある。
sennaを使えばMySQLで日本語の全文検索が可能になる。
しかしsennaは純粋なライブラリである。MySQLからそれを利用するにはMySQLをコンパイルして、sennaを組み込む必要がある。この手間を省くべく、tritonnというソフトウェアが存在する。
今回はこのtritonnを利用して、MySQLでの全文検索を利用可能にした。
インストール済みの MySQLパッケージを削除
利用している ubuntuには、apt-get install で MySQLパッケージを導入していた。
これとtritonnがぶつかるので、以下のパッケージを削除した。
例:
apt-get remove mysql-client-5.0
senna 組込み済みの MySQLをインストール
すごく丁寧な説明がここにある。
http://qwik.jp/tritonn/installtarball.html
このとおりにやれば、問題なし。
DBのテーブルに FULLTEXT インデックスを追加
以下のようにして、テーブルにFULLTEXTインデックスを追加した。
class CreateVideoItems < ActiveRecord::Migration def self.up create_table (:video_items, :options => "ENGINE MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_unicode_ci") do |t| t.string :vid t.string :title t.text :my_comment t.text :tags t.string :thumbnail_url t.timestamps end add_index :video_items, :vid, :unique=>true execute "CREATE FULLTEXT INDEX idx_my_comment ON video_items(my_comment)" execute "CREATE FULLTEXT INDEX ids_tags ON video_items(tags)" end def self.down drop_table :video_items end end
以下の点に注意。
will_paginate を導入
日本語のサイトを見て、そのとおりにやったけどうまくいかなかった。
undefined method `paginate'
なんてエラーが発生。
そこで、本家のGitHub - mislav/will_paginate: Pagination library for Rails, Sinatra, Merb, DataMapper, and moreを参照してwill_paginateを導入した。
まずはインストール。
gem install mislav-will_paginate --source http://gems.github.com/
"config/environment.rb"の最後に、以下を追加する。
gem 'mislav-will_paginate', '~> 2.2'
require 'will_paginate'
インストールはこれでOK。
次はコントローラの修正。
#@items = VideoItem.find(:all) @items = VideoItem.paginate(:all,:per_page => 10, :page => params[:page])
ポイントは
(1) "find"だったところを"paginate"に変更。
(2) パラメータに1ページあたりの表示件数である :per_page を追加。
(3) パラメータに、表示対象のページ番号を示す :page を追加。
params[:page]は、以降でViewに追加する項目(タグ)で自動的に追加される。
次にビューの修正。
以下をページのナビゲータを表示したい箇所に追加する。
<%= will_paginate @items %>
これで終了。
gemのアップデート後にエラー:uninitialized constant Gem::GemRunner (NameError)
Ubuntu上のgemをアップデートしたら、uninitialized constant Gem::GemRunner (NameError)というエラーが出るようになってしまった・・・
ぐぐってみたら、こんなページ(Ubuntuでrubygemsを1.0.1にudpateしたら"uninitialized constant Gem::GemRunner(NameError)"のエラー - iビジネス&テクノロジー)が
一応、Rails Forumの該当トピックを参考に、/usr/bin/gemの10行目(require 'rubygems'の下の行)に require 'rubygems/gem_runner' の一行を追加することで解決。激しく気持ち悪いですが・・・
同様にして、解決。
さらに参考ページはこちら。
http://weblog.rubyonrails.com/2007/12/19/trouble-installing-new-gems
カラムの名前を変更する(rename)
video_items テーブルのthumbnailカラムの名前を変更する。
まずはマイグレーションファイルを作成する。
ruby script/generate migration rename_column_thumbnail
このファイルを以下のように修正。
class RenameColumnThumbnail < ActiveRecord::Migration def self.up rename_column :video_items, :thumbnail, :thumbnail_url end def self.down rename_column :video_items, :thumbnail_url, :thumbnail end end
マイグレーションを実行する。
rake db:migrate
railsでAjaxを使う
- erbファイルに呼び出し部分を書く。 --> xxx.html.erb
- 必要なjavascriptファイルをロードするよう、呼び出し元erbファイルを編集する。
- Ajaxで更新する部分を部分テンプレートにする。--> part.html.erb
- 部分テンプレートを呼び出すRJSファイルを書く。--> action_name.rjs
- 呼び出し側をかく。--> yyy_controller.rb
javascript ファイルの呼び出しはこんな感じ。
<head> <%= javascript_include_tag :defaults%> </head>
erbファイルでのAjax呼び出し部分はこんな感じ。
form_remote_tag を使った。
<% form_remote_tag( :url => {:action => :watch_video, :vid => entry.id}) do %> <%= submit_tag "watch" %> <% end %>
link_to_remote というメソッドもある。
controller では画面に表示する情報を編集して、RJSファイルに引き渡す。
respond_to do |format| format.js # { render :action => "#{action_name}.rjs" } end
呼び出しの階層関係は、
browser --> controller --> RJSファイル --> 部分テンプレート --> browser
となる。
ちょっと面倒くさいが、こうすると部分テンプレートを部品化できる。
カラムにインデックスを付ける
video_items テーブルのvidカラムにインデックスを追加する。
まずはマイグレーションファイルを作成する。
ruby script/generate migration add_index_on_vid
このファイルを以下のように修正。
class AddIndexOnVid < ActiveRecord::Migration def self.up add_index :video_items, :vid, :unique=>true end def self.down remove_index :video_items, :vid end end
マイグレーションを実行する。
rake db:migrate
rails アプリにAJAX的な動作を組み込む
さて、これまでのところでvideo_itemデータをメンテする画面ができたので、
これを別の画面からAJAX的に呼び出す仕組みを取り入れる。