都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

『 昨日から片頭痛ある 』、『 昨日から頭痛がある 』という文がCONTAINS 関数で『 頭痛 』を指定すると、『 昨日から片頭痛ある 』という文がヒットしないので、なんとかヒットさせる術がないかどうか悩んでみたり、色々な人にヒアリングしたけど、やっぱりワードブレーカーを作る暇はないので、少し格好悪いけど『アノ』案でいくことに決めたので、内容をまとめてみた

今回のやることを説明してみる

 前回問題としていた下記のブログ内容の解決策となる方式を試してみます。今日は出張で移動時間が長いので、移動中にブログを書いて、検証も終わらせてしまいます!

『 昨日から片頭痛ある 』、『 昨日から頭痛がある 』という文がCONTAINS 関数で『 頭痛 』を指定すると、『 昨日から片頭痛ある 』という文がヒットしないので、なんとかヒットさせる術がないかどうか悩んでみる - 都内で働くSEの技術的なひとりごと

使用する環境を説明してみる

 今回は、Microsoft Azure 上の仮想サーバではなく、私の Windows 8.1 Update1、64ビット 上で 動作している  SQL Server 2014 です。前回と同じデータベースを使用しています。

実際に試してみる

 前回の記事でいろいろ悩んだわけですが.......最終案は下記の通りです。※WordBreaker を作るのは、開発期間とかいろいろ加味すると時間が足りないな...と。

  • 文を MeCab 等で解析し、分割された単語をスペースで区切って、SQL Server に格納します。これにより、SQL Server のお茶目なワードブレーカーでも完全にワードブレークすることができます。格納されたデータは、下図の通りです。

    f:id:koogucc11:20141010153920p:plain

  • 検索時は、入力された文を MeCab 等で解析し、分割された結果をすべて CONTAINS の条件に AND で指定します。たとえば、検索キーワードに『片頭痛』と入力された場合は、下図のように解析されます。

    f:id:koogucc11:20141010160847p:plain

    『片』と『頭痛』に分割されたので、それぞれ AND 条件として下記の通り設定します。

    1
    2
    
    USE TestDB
    SELECT * FROM dbo.TestTable WHERE CONTAINS(col2,'"片*" AND "頭痛*"');
  • f:id:koogucc11:20141010154446p:plain

    検索条件を『頭痛』にした場合は、きちんと二行ヒットします。

    1
    2
    
    USE TestDB
    SELECT * FROM dbo.TestTable WHERE CONTAINS(col2,'"頭痛*"');

    f:id:koogucc11:20141010154657p:plain

 sys.dm_fts_index_keywords (Transact-SQL) できちんとワードブレークされているか確認してみましょう。下記のクエリを実行してみましょう。

1
SELECT * FROM sys.dm_fts_index_keywords(db_id('Testdb'), object_id('dbo.TestTable'))

f:id:koogucc11:20141010160357p:plain

 『から』が 2文書、『昨日』が2文書、『片』が1文書、『頭痛』が2文書と解析されています。SQL Server が想定通りの解析をやってくれました!( 当然ですよね... )

おわりに一言いってみる

  電車で記事を書いて、検証をするのは結構つらいです。( 新幹線であれば問題ないのですが..... )