プラグインDMSFの検索エンジンをHyper Estraierへ替える¶
DMSFとRedmineの関係¶
DMSFはRedmineが標準で備える種々の文書管理を一つにまとめて置き換えようとしたものです.ユーザーインターフェイスは優れていますが,残念ながら検索エンジンにXapianを利用しており,そのままでは日本語に対応できません.そこで,Hyper Estraierへ置き換えるわけですが,改造はエンジンのみの置き換えで済むので,DMSFの基本的な構造は変わりません.
その要点は次のとおりです.
注)$REDMINE_ROOTは自動的に設定される環境変数ではありません.ここでは便宜的に使います.
- DMSFが管理する文書*1はすべて $REDMINE_ROOT/files/dmsf へ置かれる.
- プロセスが定期的に動作して,インデックスファイル $REDMINE_ROOT/files/index_dmsf を作成する*2.
【例】"whitemine" というディレクトリにRedmineがインストールされている場合
これは,DMSFの設定画面にも現れています.またこの画面では,Xapianに由来する設定がありますが,それがHyper Estraierでは不要になります.
ここでは,オリジナルを(ちょっと手を抜いた)次の方針で改造することにします.
- Web画面に "Xapian" 由来の設定などがあれば,それはそのままにし,削除しない.
- Web画面に Estraier に対応するものがあれば,それは "Estraier" へと修正する.(現バージョンではない)
- エラーメッセージなどに "Xapian" という文字列があれば,それは "Estraier" へと上書きする.
- ソースコード中 "Xapian" を呼び出す部分は削除する.(ロジックの変更)
- ソースコード中 "Xapian" という変数名がそのまま "Estraier" へと置き換えられる部分は "Estraier" へと修正する.
ソースコード中 "Xapian" というラベル名称はそのまま利用する.- バージョンは,日本語版であることを示すため,1.yy.zz-JP とする.
さて,変更するファイルは次の3つです.
- config/locales/ja.yml
- init.rb
- app/views/settings/_dmsf_settings.erb
- app/models/dmsf_file.rb
config/locales/ja.ymlの修正¶
コード中のラベルも含めて,Xapian から Estraier へと修正しています.
@@ -156,7 +156,7 @@ :error_file_storage_directory_does_not_exist: "ファイル保存フォルダが存在せず作ることもできません" :error_file_can_not_be_created: "ファイルを保存フォルダに作ることができません" :error_wrong_zip_encoding: "Zip エンコーディングが正しくありません" - :warning_xapian_not_available: "Xapian が利用できる状態になっていません" + :warning_estraier_not_available: "Hyper Estraier が利用できる状態になっていません" :menu_dmsf: "DMSF" :label_physical_file_delete: "物理ファイルの削除" :user_is_not_project_member: "あなたはプロジェクトのメンバーではありません"
init.rbの修正¶
先の方針に基づいて,バージョン番号をユニークにします.
@@ -29,7 +29,7 @@ name "DMSF" author "Vít Jonáš" description "Document Management System Features" - version "1.2.1" + version "1.2.1-JP" url "http://code.google.com/p/redmine-dmsf/" author_url "mailto:vit.jonas@gmail.com"
app/views/settings/_dmsf_settings.erb¶
ロードする(require する)ライブラリを xapian から estraier に変更します.加えて,先の ya.yml に対応する警告のラベルと一致させます.
抽出方針(Stem)に相当する部分も,変数名を xapian から estraier へと修正していますが,Xapian は機能しませんので,これはおまけと考えて下さい.
@@ -75,22 +75,22 @@ <hr /> <% begin - require 'xapian' - xapian_disabled = false + require 'estraier' + estraier_disabled = false rescue LoadError %> - <p class="warning"><%= l(:warning_xapian_not_available) %></p> -<% xapian_disabled = true + <p class="warning"><%= l(:warning_estraier_not_available) %></p> +<% estraier_disabled = true end %> <p> <%=content_tag(:label, l(:label_index_database) + ":") %> - <%=text_field_tag 'settings[dmsf_index_database]', @settings['dmsf_index_database'], :disabled => xapian_disabled, :size=>50 %><br/> + <%=text_field_tag 'settings[dmsf_index_database]', @settings['dmsf_index_database'], :disabled => estraier_disabled, :size=>50 %><br/> (<%=l(:label_default)%>: <%="#{RAILS_ROOT}/files/dmsf_index"%>) </p> <p> <%=content_tag(:label, l(:label_stemming_language) + ":") %> - <%=text_field_tag 'settings[dmsf_stemming_lang]', @settings['dmsf_stemming_lang'], :disabled => xapian_disabled %><br/> + <%=text_field_tag 'settings[dmsf_stemming_lang]', @settings['dmsf_stemming_lang'], :disabled => estraier_disabled %><br/> (<%=l(:label_default)%>: english )<br/> <br/> <%=l(:note_possible_values)%>: danish dutch english finnish french german german2 hungarian italian kraaij_pohlmann lovins norwegian porter portuguese romanian russian spanish swedish turkish (<%=l(:note_pass_none_to_disable_stemming)%>) @@ -98,9 +98,9 @@ <p> <%=content_tag(:label, l(:label_stem_strategy) + ":")%> - <%=radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_NONE', @settings['dmsf_stemming_strategy'] == 'STEM_NONE', :disabled => xapian_disabled, :checked=>true %> <%=l(:option_stem_none)%><br> - <%=radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_SOME', @settings['dmsf_stemming_strategy'] == 'STEM_SOME', :disabled => xapian_disabled %> <%=l(:option_stem_some)%><br> - <%=radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_ALL', @settings['dmsf_stemming_strategy'] == 'STEM_ALL', :disabled => xapian_disabled %> <%=l(:option_stem_all)%><br> + <%=radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_NONE', @settings['dmsf_stemming_strategy'] == 'STEM_NONE', :disabled => estraier_disabled, :checked=>true %> <%=l(:option_stem_none)%><br> + <%=radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_SOME', @settings['dmsf_stemming_strategy'] == 'STEM_SOME', :disabled => estraier_disabled %> <%=l(:option_stem_some)%><br> + <%=radio_button_tag 'settings[dmsf_stemming_strategy]', 'STEM_ALL', @settings['dmsf_stemming_strategy'] == 'STEM_ALL', :disabled => estraier_disabled %> <%=l(:option_stem_all)%><br> <br/> <%=l(:label_stemming_description)%>: <br>
app/models/dmsf_file.rb¶
検索機能本体の修正をします.主な修正の要点は次のとおりです.
XapianではなくてEstraier を呼び出します.呼び出し時のエラー処理はXapianと同様です.
エラーや警告のメッセージも, Estraier のそれへと修正します.
インデックスデータベースへのアクセスメソッドは,Xapianとは大幅に異なりますので,ざっくりと削除し,上書きします.
まず,コードの冒頭には,ライブラリの存在の有無によるエラー処理があります.
@@ -17,11 +17,11 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. begin - require 'xapian' - $xapian_bindings_available = true + require 'estraier' + $estraier_bindings_available = true rescue LoadError - Rails.logger.info "REDMAIN_XAPIAN ERROR: No Ruby bindings for Xapian installed !!. PLEASE install Xapian search engine interface for Ruby." - $xapian_bindings_available = false + Rails.logger.info "REDMAIN_ESTRAIER ERROR: No Ruby bindings for Estraier installed !!. PLEASE install Hyper Estraier search engine interface for Ruby." + $estraier_bindings_available = false end
次に,インデックスデータベースへのアクセスについて,エラー処理があります.
@@ -260,46 +260,37 @@ end end - if !options[:titles_only] && $xapian_bindings_available + if !options[:titles_only] && $estraier_bindings_available database = nil begin - database = Xapian::Database.new(Setting.plugin_redmine_dmsf["dmsf_index_database"].strip) + database = Estraier::Database::new + database.open(Setting.plugin_redmine_dmsf["dmsf_index_database"].strip, Estraier::Database::DBREADER) rescue - Rails.logger.warn "REDMAIN_XAPIAN ERROR: Xapian database is not properly set or initiated or is corrupted." + Rails.logger.warn "REDMAIN_ESTRAIER ERROR: Estraier database is not properly set or initiated or is corrupted." end
database.nil 以下は大幅に構造が異なりますので,ざっくりと入れ替えましょう.
unless database.nil? - enquire = Xapian::Enquire.new(database) + # create a search condition object + cond = Estraier::Condition::new - queryString = tokens.join(' ') - qp = Xapian::QueryParser.new() - stemmer = Xapian::Stem.new(Setting.plugin_redmine_dmsf['dmsf_stemming_lang'].strip) - qp.stemmer = stemmer - qp.database = database - - case Setting.plugin_redmine_dmsf['dmsf_stemming_strategy'].strip - when "STEM_NONE" then qp.stemming_strategy = Xapian::QueryParser::STEM_NONE - when "STEM_SOME" then qp.stemming_strategy = Xapian::QueryParser::STEM_SOME - when "STEM_ALL" then qp.stemming_strategy = Xapian::QueryParser::STEM_ALL - end - - if options[:all_words] - qp.default_op = Xapian::Query::OP_AND - else - qp.default_op = Xapian::Query::OP_OR - end - - query = qp.parse_query(queryString) - - enquire.query = query - matchset = enquire.mset(0, 1000) - - unless matchset.nil? - matchset.matches.each {|m| - docdata = m.document.data{url} - dochash = Hash[*docdata.scan(/(url|sample|modtime|type|size)=\/?([^\n\]]+)/).flatten] - filename = dochash["url"] - if !filename.nil? + # set the search phrase to the search condition object + queryString = tokens.join(options[:all_words] ? ' AND ': ' OR ') + cond.set_phrase(queryString ) + + # get the result of search + result = database.search(cond) + + if result + # for each document in the result + dnum = result.doc_num + for i in 0...dnum + # retrieve the document object + doc = database.get_doc(result.get_doc_id(i), 0) + next unless doc + # display attributes + uri = doc.attr("@uri") + if uri + filename = uri.sub(/.*\//, '') dmsf_attrs = filename.split("_") next if dmsf_attrs[1].blank? next unless results.select{|f| f.id.to_s == dmsf_attrs[1]}.empty?
最後にインデックスデータベースを閉じて終了です.
@@ -331,9 +322,14 @@ end end end - } end end + + # close the database + unless database.close + Rails.logger.warn(database.err_msg(database.error)) + end + end # unless database.nil? end [results, results_count]
修正は以上です.
- *1 DMSFが管理する文書:ファイル名が同じであっても,インデックスは異なるよう,接頭辞が付いています.
- *2 $REDMINE_ROOT/files/index_dmsf を作成する:これは管理者が設定できるのですが,わかりやすくするため,推奨としました.
Updated by Masanori Machii about 13 years ago · 10 revisions