« 2007年12月 | メイン | 2008年02月 »

2008年01月24日

[MySQL][Rails] MySQL+Sennaの全文検索でスコア順にソートする。

こんにちわ。ばたっちです。

MySQL+Sennaな環境の全文検索について覚書。

  • 日本語でAND検索する→BOOLEAN MODEかつ「*D+」を付与
  • BOOLEAN MODEだとスコア順にならない→match() against()がスコアを返す

それぞれ反映したら SQLはこんなカンジになります。


SELECT *, match(text) against('*D+ 単語1 単語2' in boolean mode) AS score
  FROM table1s
 WHERE match(text) against('*D+ 単語1 単語2' in boolean mode)
 ORDER BY score DESC;

無理やり Railsにからめて(^^;、ActiveRecordではこんなカンジ。


match = "match(text) against('*D+ #{terms.join(' ')}' in boolean mode)
results = Table1.find(:all, :select => "*, #{match} AS score",
                      :conditions => match, :order => "score DESC")

これで BOOLEAN MODEでもマッチ率順になるので、LIMITで上位件数の絞込みできますね。φ(.. )

[Rails] SQLiteアダプタのtime型のマッピング修正。

こんにちわ。ばたっちです。

ついでに、ActiveRecord の SQLiteアダプタの修正です。
time型のマッピングが datetimeになってたので。。


module ActiveRecord
  module ConnectionAdapters #:nodoc:
    class SQLiteAdapter < AbstractAdapter
      def native_database_types #:nodoc:
        {
          :primary_key => default_primary_key_type,
          :string      => { :name => "varchar", :limit => 255 },
          :text        => { :name => "text" },
          :integer     => { :name => "integer" },
          :float       => { :name => "float" },
          :decimal     => { :name => "decimal" },
          :datetime    => { :name => "datetime" },
          :timestamp   => { :name => "datetime" },
-         :time        => { :name => "datetime" },
+         :time        => { :name => "time" },
          :date        => { :name => "date" },
          :binary      => { :name => "blob" },
          :boolean     => { :name => "boolean" }
        }
      end
    end
  end
end

「HTTPレスポンスのヘッダ折りたたみ。」の同じく、lib/ 以下に上記のファイルを配置して、config/environment.rb読み込みます。

以前、MySQLアダプタでも同様の間違いがあったように思う(今は直ってる)ので、いつかは修正されるかと。。

[Ruby][Rails] ログ出力フォーマットを変えたい!

こんにちわ。ばたっちです。

Rails標準のLoggerは、ログ出力フォーマットを簡単にいじれないっていうけど、ホント簡単にはできない。。orz

以下の方法でできたので覚書。もっといい方法があるだろうけど。

  • active_support の clean_logger.rb を lib/ 以下にコピー。
    (標準 Logger には独自の Formatter を設定できるんだけどバグってるぽくて、 その辺の修正とかされているみたい)
  • lib/以下に Formatter の拡張クラスを作る。
    
    class MyFormatter < Logger::Formatter
      Format = "[%s] %s:%s: %s\n"
      def call(severity, time, progname, msg)
        Format % [format_datetime(time), severity, progname, msg2str(msg)]
      end
      private
        def format_datetime(time)
          time.strftime("%Y-%m-%d %H:%M:%S.") << "%06d" % time.usec
        end
    end
    ----
    こんなログイメージ。
    =>[2008-01-24 00:00:00.000000] INFO:user/login: ログインしたす。
    
  • config/environment.rb で RAILS_DEFAULT_LOGGER に Formatter を設定。
    
    RAILS_DEFAULT_LOGGER = Logger.new("#{RAILS_ROOT}/log/#{RAILS_ENV}.log")
    RAILS_DEFAULT_LOGGER.formatter = MyFormatter.new
    

ちょっと面倒だけど、なんでもできてしまうものですね。(^^)v