Skip to content

Instantly share code, notes, and snippets.

@whosaysni
Last active December 2, 2019 12:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save whosaysni/ab239546354f8d8f6bcec3f644294604 to your computer and use it in GitHub Desktop.
Save whosaysni/ab239546354f8d8f6bcec3f644294604 to your computer and use it in GitHub Desktop.
Sphinxの日本語複合語検索を大雑把化する

これは何?

Sphinxで日本語検索をするときに、複合語をバラしてインデクス上の語にヒットさせやすくする小技です。

Sphinx で日本語検索インデクスを生成させる場合、デフォルトの設定では、TinySegmenterのPython版を使って単語を切り出します。 一方で、検索ページのフォームは、入力に日本語の複合語が入っていても単語の切り出しを行わず、複合語のままでインデクスを走査します。 その結果、例えば、元の文章に「システムの標準」という語が入っていて、そこから「標準」、「システム」というインデクスが生成されていると、「標準システム」「標準のシステム」「システム標準」などを検索してもヒットしません。

この修正では、検索フォームに入力された単語を、JavaScript版のTinySegmenter(Python版の元となったオリジナル)で分割することによって、複合語での検索語入力(例:「システム標準」)を、よりインデクスに近い複数の単一語での検索入力(例:「システム」と「標準」)に置き換えます。 その結果、よりインデクス上の単語にヒットしやすくなり、検索の精度は落ちますが、 "大雑把に" ページを探せるようになります。

手順

  • sphinxプロジェクトディレクトリに _static, _templates ディレクトリを作成します。
  • http://chasen.org/~taku/software/TinySegmenter/tiny_segmenter-0.2.js を _static の下に配置します。
  • search.html を _templates の下に配置します。
  • conf.py に下記を追加します:

    html_static_path = ['_static']
    templates_path = ['_templates']
    def setup(app):
        app.add_javascript('tiny_segmenter.js')
  • make clean; make html します。

以上

追伸

  extension 化しておきました。 https://pypi.python.org/pypi/sphinx-tsegsearch/1.0

{%- extends "basic/search.html" %}
{% block extrahead %}
{{ super() }}
<script type="text/javascript">
function splitQuery(query) {
var segmenter = new TinySegmenter();
var result = [];
var start = -1;
for (var i = 0; i < query.length; i++) {
if (splitChars[query.charCodeAt(i)]) {
if (start !== -1) {
var segs = segmenter.segment(query.slice(start, i));
result = result.concat(segs);
start = -1;
}
} else if (start === -1) {
start = i;
}
}
if (start !== -1) {
var segs = segmenter.segment(query.slice(start, i));
result = result.concat(segs);
}
return result.filter(function(s){ return s.length>1; }, result);
};
</script>
{% endblock extrahead %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment