オープンソースのナレッジベース(Knowledge Base) 「SCIRET」で日本語の記事を日本語で検索すると、本来はヒットするはずの検索文字列で検索しても1件もヒットしないということが結構ある。
また、ホーム画面の検索ボックスで検索してもヒットしないが、アドバンスドサーチで検索をかけるとヒットしたりする。
本記事でその原因と対処方法を簡単に説明する。
SCIRETについて
オープンソースのナレッジベース「SCIRET」についての詳細は以下を参照。


SCIRETで検索文字列がヒットしない理由
「SCIRET」のホーム画面の検索ボックスで検索文字列を入力すると、データベースに送られるSQL文は、「MATCH (title, content, url) AGAINST(?)」を使ったSQL文が送られる。
一方アドバンスドサーチでは、「Like '%検索文字列%'」 を使ったSQL文が送られる。
「MATCH (title, content, url) AGAINST(?)」での検索は、MySQLのフルテキストインデックス(FULLTEXT INDEX)機能を使用した検索になる。
MySQLのフルテキストインデックスは、残念ながら日本語のデータに対してはうまく機能しない。
なぜ機能しないかというと、日本語独特の文章規則(単語間の区切りがない)が原因になっている。
MySQLのフルテキスト機能を日本語で利用するためには、MeCabやChasenなどの形態素解析 (わかち書き)ソフトを使うなど、ちょっとめんどくさい処理が必要。
MySQLのフルテキストインデックスの詳細については、「MySQLで全文検索 - FULLTEXTインデックスの基礎知識」などを参考。
というわけで、「SCIRET」のホーム画面からの検索でもアドバンスドサーチと同様に「Like '%検索文字列%'」で検索をかけさせたい場合のコード変更箇所と変更内容を以下に記述する。
SCIRETで検索文字列きちんとヒットするようにする設定手順
以下コードの一部を変更して日本語検索文字列がきちんとヒットするようにする設定方法について記載する。
SCIRETのフォルダのサブフォルダ「models」フォルダ(sciret\models)を開く。
「models」フォルダのファイルの一覧に「ArticleGateway.php」というファイルがあるのでこのファイルをメモ帳などのテキストエディタで開く。
開いたらgetSearchResults関数のMATCHを使ったWhere句を作成しているコード部分(157~158行目)を以下のように変更する。
変更前(以下の2行を削除)
$whereArr[] = 'MATCH (title, content, url) AGAINST(?)';
$where = implode(' AND ', $whereArr);
変更後(上記2行の代わりに以下のコードを貼り付ける)
//全角スペースを半角スペースに変換
$searchQuery = mb_convert_kana($searchQuery, "s");
$wordList = explode(' ',$searchQuery);
for ($i = 0; $i < count($wordList); $i++) {
$wordList[$i] = $this->db->escape_string($wordList[$i]);
$wordList[$i] = "(title LIKE '%{$wordList[$i]}%' OR content LIKE '%{$wordList[$i]}%')";
}
$whereArr[] = implode(' AND ', $wordList);
$where = implode(' AND ', $whereArr) ;
$where = $where;
修正が終わったら上書き保存する。
以上で設定作業は終了。
以降は、ホーム画面から検索しても「Like '%検索文字列%'」で検索するようになる。
また、検索文字列の区切りは、半角もしくは全角のスペースが区切りとなる。
つまり、"sciret"と"ナレッジ"という文字を含む記事を抽出したい場合は、"sciret ナレッジ"と入力するか、"sciret ナレッジ"と入力すればよい。(検索文字列は、何個でも良い)
当然「Like」を使った検索になるため、記事数が膨大になるとパフォーマンスが悪くなることに注意すること。
ちなみに自分の会社で運用しているが、1000件程度の記事数では検索速度についてはまったく支障がない。
コメント