最近社内のドキュメントは殆どSphinxで書いてます。しかしどうも検索の精度が悪い、特に複合語がヒットしないと言われたので改善してみました。Sphinxのバージョンはv1.2.2です。
まずはドキュメントに全文検索機能を追加する
こんな方法で追加しました。
sphinx-quickstart
でドキュメント作成conf.py
に全文検索の設定を追加
123pythonhtml_search_language = 'ja'html_search_options = {'type':'default'} # build server using type:mecabmake html
改善案1: searchtools.jsを賢くする
_build/html/_static/searchtools.js
にパッチを当てます。
生成物にパッチを当てるのは気持ち悪いけど説明の簡便のため、というか私のSphinxやPythonへの理解が低いのでとりあえずこうします。もっとよい方法があれば教えてください。
パッチが何をしてるかというと、元々Sphinxがsearchindex.js
へ出力する索引は転置インデックスindex.terms
がオブジェクトリテラルで作成されます。これだと単語が完全一致した時しかインデックスを取得できません。オブジェクトリテラルをソート済みの配列にすることで2分探索+前方一致検索が可能になります。
ソート済みの配列への変換は簡便のためSearch.setIndex
でやってます。本来は変換したものをsearchindex.js
に出力したほうがよいでしょう。
こんな配列の索引が出来上がったとします。
1 2 3 |
1. ["データ", 1] 2. ["データベース", 2] 3. ["移行", 1] |
2分探索はSearch._performTermsSearch
内でやってます。このbinarySearch
は索引内に検索語があるかどうかに関係なく検索語の辞書順での位置を返します。そこから後ろ方向に前方一致検索することで、例えば検索語が「データ」の場合「データ」だけでなく「データベース」もヒットさせることができます。
しかしこれだけだと検索語が複合語の場合、例えば「データ移行」がヒットしません。そこで2分探索の結果を前方向に、今度は検索語が索引内の単語で始まるかどうかをチェックします。そして「データ」がヒットしたら「データ」と「移行」でAND検索したものとしてその結果を返します。「データ」と「移行」が離れてる文書もヒットしますが、それが問題になるようであればdisplayNextItem
内の$.ajax#complete
で除外すればよいでしょう。
文書の内容や索引の作り方にもよりますが、元のよりは複合語に強くなったと思います。
改善案2: oktaviaを使う
- https://github.com/shibukawa/oktavia
- http://oktavia.info/ja/pages/doc/install_to_sphinx.html
- http://blog.shibu.jp/article/80248541.html
oktaviaは渋川よしきさんが作成したFM-indexによる検索エンジンです。単語の境界に関係なくすべての文書に対し部分一致検索ができます。
非常に魅力的な検索エンジンなのですが、ドキュメントが現行バージョンの1.0に追いついてない、バグと思われる挙動がある、など導入するには少しハードルが高いという印象を受けました。渋川さんに教えていただいた内容を元に私が検証した結果を記しておきます。リビジョンは 8ed26702c90994b621dc426dd16f84debe728799 です。バージョン0.5は安定してるそうです(未検証)。
まずはoktaviaをインストールします。
1 2 3 |
git clone https://github.com/shibukawa/oktavia.git cd oktavia npm install |
次に私の作ったパッチをマージします。
- 非Web Worker版が動かない問題
- -fオプションで指定したフィルタが効かないことがある問題
- スニペットのハイライトがずれる問題
- スニペットに検索語が入らないことがある問題
- 大文字小文字を無視した検索対応
oktavia-mkindex-cliで索引を作成します。
1 2 3 4 5 6 7 8 |
grunt build # -I オプションは「大文字小文字を無視した検索対応」パッチをマージした時のみ有効 ./bin/oktavia-mkindex-cli -i ../_build/html/ -r ../_build/html/ -m html -u file -f .body -c 5 -t web -o ../_build/html/searchindex.oktavia.js -I # search.htmlで使うファイルをコピー cp ./bin/web/oktavia-jquery-ui.js ../_build/html/oktavia-jquery-ui.js cp ./templates/sphinx/_static/searchstyle.css ../_build/html/searchstyle.css |
oktaviaのファイルをhtmlに追加します。確認だけなら生成した_build/html/search.html
を変更するのが楽ですが、本来は_templates/searchbox.html
などで追加するのがよいと思われます。
1 2 3 |
<!-- headに追加 --> <script type="text/javascript" src="oktavia-jquery-ui.js"></script> <link rel="stylesheet" href="searchstyle.css" type="text/css" /> |
1 2 |
<!-- bodyに追加 --> <div id="oktavia_search_form" data-index="searchindex.oktavia.js"></div> |
search.html
をブラウザで表示すれば検索可能です。検索結果がポップアップで表示されるなど元のSphinxのUIとは異なるので、元のと同じにしたい場合はoktavia-jquery-ui.js
を変更する必要があります。
searchtools.js
の改善だけでそこそこよくなったので今回はoktaviaの採用を見送りました。ただSphinxの検索エンジンをデフォルトでoktaviaにするという話もあるらしいと聞いています。もしそうなればこのような面倒な改造を行わなくとも、手軽に快適な全文検索ができるようになるでしょう。私はデフォルトでoktaviaが使える未来を望んでます。
最近のコメント