textsearch_jaで全文検索

             日本PostgreSQLユーザ会
                 北海道支部
           株式会社サイクル・オブ・フィフス
                  石田朗...
自己紹介
 ●   id:iakio
      ●    http://postgresql.g.hatena.ne.jp/iakio/
      ●    今日の資料とデモのソースコードは公開します




09/06/20
自己紹介
 ●    代表作
        ●     SQLでボウリングのスコアを計算
 with recursive
 s(idx, pins1, pins2, pins3) as (
      select s1.idx, s1.pi...
告知など
 ●   PostgreSQL的な話
      ●    8.4RC1が6/14に出ました
 ●   JPUG北海道支部的な話
      ●    5/13に勉強会を開催
      ●    次は7/8?
 ●   JPUG的な...
PostgreSQLと全文検索




09/06/20
PostgreSQLでの全文検索
 ●   PostgreSQL8.2以前
      ●    contrib/tsearch2
 ●   PostgreSQL8.3
      ●    全文検索機能が本体に含まれるようになった。
    ...
資料に自信が無いので
            とりあえずデモ




09/06/20
デモの構成
 ●   PostgreSQL 8.4RC1(8.3でも同じです)
 ●   データベースエンコーディングはutf-8
 ●   PostgreSQLのドキュメントを格納したテーブル(html)
 ●   レコード数:900くらい
...
とりあえず検索する方法




09/06/20
方法1:関数インデックス
 ●   インデックスを1つ作るだけで高速な全文検索ができ
     る

 => SELECT title FROM docs_en WHERE body ILIKE '%search%';




 インデックス作...
全文検索の基本
 ●   tsvector、tsqueryはそれぞれデータ型
 ●   to_tsvector、(plain)to_tsqueryはtext型をtsvector、
     tsqueryに変換する関数



         ...
方法2:tsvector用の列を追加
 ●   高速。特にスコアによるソートをする場合
 ●   本文が更新された時にtsvectorは自動的に更新されな
     い(トリガやバッチを使う必要がある)
 ●   容量は大きくなる


 => ...
LIKEと全文検索の違い

                                   => select count(*) from docs_en
 => select count(*) from docs_en    where...
tsvectorができるまで




09/06/20
転置インデックス

           1    単語1 単語2                単語1   1,2,4
           2   単語1 単語3 単語5             単語2   1,3
           3...
to_tsvector
 ●    Parserが文章を23種類のtokenに分解
            a fat cat sat on a mat - it <b>ate</b> a fat rats

     Word, all AS...
to_tsvector
 ●    token種別毎に正規化
                       Stopwordの削除
                         語幹に縮小

     Word, all ASCII    ...
token
 => select * from ts_token_type('default');
  tokid |      alias      |                description
 -------+--------...
Dictionaries
 => dF+ english
  Text search configuration "pg_catalog.english"
 Parser: "pg_catalog.default"
        Token ...
Dictionary
 ●   ストップワード
      ●    インデックスに格納しないトークンの削除("a","the")
 ●   Snowball
      ●    語幹縮小"queries" => "queri"
 => se...
Dictionary
 ●   Simple、Sysnonym、Ispell、Thesaurus、Snowball
 ●   share/tsearch_data/
 ●   どのtoken typeにどの辞書を適用するかは変更可能
     ...
LIKEと全文検索の違い

                                   => select count(*) from docs_en
 => select count(*) from docs_en    where...
ここまでのまとめ
 ●   Token種別"tag"に対してDictionaryが設定されていない
     ので、htmlタグはtsvectorでは無視される
 ●   Token種別"asciiword"に対して設定された辞
     書"...
全文検索の機能




09/06/20
問い合わせ式 - tsquery
 ●   to_tsquery()
      ●    '&'(AND)、'|'(OR)、'!'(NOT)、括弧
      ●    詳細な検索条件が指定できるが、構文エラーに注意
 ●   plainto...
ts_rank
 ●   ts_rank([weights float4[], ] vector tsvector, query
     tsquery[, normalization]) returns float4
      ●    ...
ts_headline
 ●   ts_headline([regconfig, ]text, tsquery[, text])
      ●    結果の強調表示
      ●    StartSel、StopSel等設定可能



 =...
configuration
 to_tsvector('english', body)
 to_tsvector('simple', body)
 to_tsvector(body)

 ●   全文検索で使う関数のふるまいをまとめたもの
 ●...
textsearch_ja




09/06/20
textsearch_ja
 ●   default parserではわかち書きできない
 ●   http://textsearch-ja.projects.postgresql.org/
 ●   Mecabを使って形態素解析
 ●   8...
textsearch_jaのparser
 ●   非自立語を削除
 ●   動詞、助動詞を正規化
      ●    「使った」->「使う」
 ●   英数はdefault parserでparseする(htmlは削除される)
 ●   t...
textsearch_jaと他の全文検索
 ●   textsearch_jaはPostgreSQL本体の全文検索機能の拡
     張として実装されている
      ●    クラッシュリカバリやPITRを使うことができる
      ● ...
その他のtextsearch_jaの機能
 ●   というかmecabの機能
      ●    テキストの正規化(ja_normalize)
      ●    ふりがな(furigana)
      ●    ひらがな<->カタカナ(...
おまけ




09/06/20
参考
 ●   Building search.postgresql.org(PGCon 2008)
      ●    http://www.pgcon.org/2008/schedule/events/75.en.html
      ●...
●   Some recent advences in full-text search(PGcon
     2009)
      ●    http://www.pgcon.org/2009/schedule/events/119.en....
Upcoming SlideShare
Loading in …5
×

textsearch_jaで全文検索

7,163 views

Published on

PostgreSQLの全文検索機能に関するosc2009 hokkaido での発表資料です。

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
7,163
On SlideShare
0
From Embeds
0
Number of Embeds
467
Actions
Shares
0
Downloads
23
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

textsearch_jaで全文検索

  1. 1. textsearch_jaで全文検索 日本PostgreSQLユーザ会 北海道支部 株式会社サイクル・オブ・フィフス 石田朗雄 09/06/20
  2. 2. 自己紹介 ● id:iakio ● http://postgresql.g.hatena.ne.jp/iakio/ ● 今日の資料とデモのソースコードは公開します 09/06/20
  3. 3. 自己紹介 ● 代表作 ● SQLでボウリングのスコアを計算 with recursive s(idx, pins1, pins2, pins3) as ( select s1.idx, s1.pins, s2.pins, s3.pins from score s1 left join score s2 on (s2.idx = s1.idx + 1) left join score s3 on (s3.idx = s1.idx + 2) ), f(idx, pins1, pins2, pins3) as ( select idx, pins1, pins2, pins3 from s where idx = 1 union all select s.idx, s.pins1, s.pins2, s.pins3 from s join f on (s.idx = f.idx + case when f.pins1 = 10 then 1 else 2 end) ), sof(idx, pins1, pins2, pins3, score_of_frame) as ( select idx , pins1, pins2, pins3 , case when pins1 = 10 then pins1 + pins2 + pins3 when pins1 + pins2 = 10 then pins1 + pins2 + pins3 else pins1 + pins2 end as score_of_frame from f ) select row_number( ) over w as frame , pins1 , pins2 , case row_number( ) over w when 10 then pins3 else null end as pins3 , score_of_frame , sum(score_of_frame) over w from sof window w as (order by idx) 09/06/20
  4. 4. 告知など ● PostgreSQL的な話 ● 8.4RC1が6/14に出ました ● JPUG北海道支部的な話 ● 5/13に勉強会を開催 ● 次は7/8? ● JPUG的な話 ● JPUG 10th Anniversary Conference(11/20~21) 09/06/20
  5. 5. PostgreSQLと全文検索 09/06/20
  6. 6. PostgreSQLでの全文検索 ● PostgreSQL8.2以前 ● contrib/tsearch2 ● PostgreSQL8.3 ● 全文検索機能が本体に含まれるようになった。 ● 日本語は未対応 ● textsearch_ja ● 日本語で全文検索を行なうための拡張モジュール ● http://textsearch-ja.projects.postgresql.org/ ● textsearch_sennaの話は今日はありません 09/06/20
  7. 7. 資料に自信が無いので とりあえずデモ 09/06/20
  8. 8. デモの構成 ● PostgreSQL 8.4RC1(8.3でも同じです) ● データベースエンコーディングはutf-8 ● PostgreSQLのドキュメントを格納したテーブル(html) ● レコード数:900くらい ● 詳しくはブースで!! => d docs_en カラム | 型 | --------+----------+------------ id | integer | path | text | title | text | body | text | 09/06/20
  9. 9. とりあえず検索する方法 09/06/20
  10. 10. 方法1:関数インデックス ● インデックスを1つ作るだけで高速な全文検索ができ る => SELECT title FROM docs_en WHERE body ILIKE '%search%'; インデックス作成 => CREATE INDEX docs_en_idx ON docs_en USING GIN(to_tsvector('english', body)); CREATE INDEX 検索 => SELECT title FROM docs_en WHERE to_tsvector('english', body) @@ to_tsquery('english', 'search'); 09/06/20
  11. 11. 全文検索の基本 ● tsvector、tsqueryはそれぞれデータ型 ● to_tsvector、(plain)to_tsqueryはtext型をtsvector、 tsqueryに変換する関数 tsvector @@ tsquery (検索対象) (検索式) => True / False 09/06/20
  12. 12. 方法2:tsvector用の列を追加 ● 高速。特にスコアによるソートをする場合 ● 本文が更新された時にtsvectorは自動的に更新されな い(トリガやバッチを使う必要がある) ● 容量は大きくなる => ALTER TABLE docs_en ADD vec tsvector; ALTER TABLE => UPDATE docs_en SET vec = to_tsvector('english', body); UPDATE 936 => CREATE INDEX docs_en_idx2 ON docs_en USING GIN(vec); CREATE INDEX 検索 => SELECT title FROM docs_en WHERE vec @@ to_tsquery('english', 'search'); 09/06/20
  13. 13. LIKEと全文検索の違い => select count(*) from docs_en => select count(*) from docs_en where to_tsvector('english', body) where body ilike '%html%'; @@ to_tsquery('html'); count count ------- ------- 935 14 (1 row) (1 row) => select count(*) from docs_en => select count(*) from docs_en where to_tsvector('english', body) where body ilike '%query%'; @@ to_tsquery('query'); count count ------- ------- 312 327 (1 row) (1 row) 09/06/20
  14. 14. tsvectorができるまで 09/06/20
  15. 15. 転置インデックス 1 単語1 単語2 単語1 1,2,4 2 単語1 単語3 単語5 単語2 1,3 3 単語2 単語3 単語4 単語3 2,3 4 単語1 単語5 単語4 3 単語5 2,5 ● 単語がどの文章に含まれているか(本の索引) ● 転置インデックスを作成するためには文章を単語に分 ける必要がある(日本語の場合はわかち書き) ● GIN(Generalized Inverted Index) ● 全文検索の他にも、配列型などにも使われる 09/06/20
  16. 16. to_tsvector ● Parserが文章を23種類のtokenに分解 a fat cat sat on a mat - it <b>ate</b> a fat rats Word, all ASCII XML tag Space symbols a <b> ' ' fat </b> - cat sat on mat it ate rats 09/06/20
  17. 17. to_tsvector ● token種別毎に正規化 Stopwordの削除 語幹に縮小 Word, all ASCII Space symbols a ' ' fat fat - cat cat sat english_stem sat 削除 on XML tag mat mat <b> it </b> ate ate rats rat 09/06/20
  18. 18. token => select * from ts_token_type('default'); tokid | alias | description -------+-----------------+------------------------------------------ 1 | asciiword | Word, all ASCII 2 | word | Word, all letters 3 | numword | Word, letters and digits 4 | email | Email address 5 | url | URL 6 | host | Host 7 | sfloat | Scientific notation 8 | version | Version number 9 | hword_numpart | Hyphenated word part, letters and digits 10 | hword_part | Hyphenated word part, all letters 11 | hword_asciipart | Hyphenated word part, all ASCII 12 | blank | Space symbols 13 | tag | XML tag 14 | protocol | Protocol head ... 23 | entity | XML entity (23 rows) 09/06/20
  19. 19. Dictionaries => dF+ english Text search configuration "pg_catalog.english" Parser: "pg_catalog.default" Token | Dictionaries -----------------+------------------------------- asciihword | english_stem asciiword | english_stem email、host等は email | simple 語幹縮小しない file | simple float | simple host | simple … numword | simple sfloat | simple brankやtagにはDictionaryが uint | simple 設定されていない url | simple url_path | simple version | simple word | english_stem 09/06/20
  20. 20. Dictionary ● ストップワード ● インデックスに格納しないトークンの削除("a","the") ● Snowball ● 語幹縮小"queries" => "queri" => select to_tsvector('query queries'); to_tsvector ------------- 'queri':1,2 (1 row) => select to_tsvector('http://www.postgresql.org/about/history'); to_tsvector -------------------------------------------------------------------------------- '/about/history':3 'www.postgresql.org':2 'www.postgresql.org/about/history':1 (1 row) 09/06/20
  21. 21. Dictionary ● Simple、Sysnonym、Ispell、Thesaurus、Snowball ● share/tsearch_data/ ● どのtoken typeにどの辞書を適用するかは変更可能 (ALTER TEXT SEARCH CONFIG...) (share/tsearch_data/english.stop) i me my myself we our ours ourselves you your ... 09/06/20
  22. 22. LIKEと全文検索の違い => select count(*) from docs_en => select count(*) from docs_en where to_tsvector('english', body) where body ilike '%html%'; @@ to_tsquery('html'); count count ------- ------- 935 14 (1 row) (1 row) => select count(*) from docs_en => select count(*) from docs_en where to_tsvector('english', body) where body ilike '%query%'; @@ to_tsquery('query'); count count ------- ------- 312 327 (1 row) (1 row) 09/06/20
  23. 23. ここまでのまとめ ● Token種別"tag"に対してDictionaryが設定されていない ので、htmlタグはtsvectorでは無視される ● Token種別"asciiword"に対して設定された辞 書"english_stem"により、文字 列"query"も"queries"も"queri"と認識される 09/06/20
  24. 24. 全文検索の機能 09/06/20
  25. 25. 問い合わせ式 - tsquery ● to_tsquery() ● '&'(AND)、'|'(OR)、'!'(NOT)、括弧 ● 詳細な検索条件が指定できるが、構文エラーに注意 ● plainto_tsquery() ● Tokenを'&'で結合する ● tsquery同士を演算子(&&、||)で結合することができる => select to_tsquery('fat & cat') && !! plainto_tsquery('sat mat'); ?column? ------------------------------------ 'fat' & 'cat' & !( 'sat' & 'mat' ) (1 row) 09/06/20
  26. 26. ts_rank ● ts_rank([weights float4[], ] vector tsvector, query tsquery[, normalization]) returns float4 ● 色々オプションがあるらしい ● ts_rankの引数にはtsvectorが必要 SELECT … ts_rank(to_tsvector(body), …) => 1000件ヒットすると、1000回to_tsvector()が呼ばれる SELECT … ts_rank(vec, …) => あらかじめtsvectorの列を用意しておく 09/06/20
  27. 27. ts_headline ● ts_headline([regconfig, ]text, tsquery[, text]) ● 結果の強調表示 ● StartSel、StopSel等設定可能 => select ts_headline('fat cat sat mat', to_tsquery('cat')); ts_headline ------------------------ fat <b>cat</b> sat mat (1 row) 09/06/20
  28. 28. configuration to_tsvector('english', body) to_tsvector('simple', body) to_tsvector(body) ● 全文検索で使う関数のふるまいをまとめたもの ● 省略された場合、default_text_search_configが使われ る(postgresql.confやsetコマンドで指定できる) => dF List of text search configurations Schema | Name | Description ------------+------------+--------------------------------------- pg_catalog | danish | configuration for danish language pg_catalog | dutch | configuration for dutch language pg_catalog | english | configuration for english language 09/06/20
  29. 29. textsearch_ja 09/06/20
  30. 30. textsearch_ja ● default parserではわかち書きできない ● http://textsearch-ja.projects.postgresql.org/ ● Mecabを使って形態素解析 ● 8.3、8.4に対応。Windows用バイナリ有り => select to_tsvector('日本語を使ったfull text searchの例'); to_tsvector ------------------------------------------------ 'searchの例':3 'text':2 '日本語を使ったfull':1 (1 row) => select to_tsvector('japanese', '日本語を使ったfull text searchの例'); to_tsvector --------------------------------------------------------- 'full':3 'search':5 'text':4 '使う':2 '例':6 '日本語':1 (1 row) 09/06/20
  31. 31. textsearch_jaのparser ● 非自立語を削除 ● 動詞、助動詞を正規化 ● 「使った」->「使う」 ● 英数はdefault parserでparseする(htmlは削除される) ● tsqueryは、単語のANDになる => select to_tsquery('japanese', '全文検索'); to_tsquery ----------------- '全文' & '検索' (1 row) 09/06/20
  32. 32. textsearch_jaと他の全文検索 ● textsearch_jaはPostgreSQL本体の全文検索機能の拡 張として実装されている ● クラッシュリカバリやPITRを使うことができる ● tsearch2に対応したアプリをそのまま使える(MeidaWikiと か) ● 「PostgreSQL上にMeidaWiki環境を構築」 http://lets.postgresql.jp/documents/tutorial/mediawiki/ 09/06/20
  33. 33. その他のtextsearch_jaの機能 ● というかmecabの機能 ● テキストの正規化(ja_normalize) ● ふりがな(furigana) ● ひらがな<->カタカナ(hiragana,katakana) ● 等々 09/06/20
  34. 34. おまけ 09/06/20
  35. 35. 参考 ● Building search.postgresql.org(PGCon 2008) ● http://www.pgcon.org/2008/schedule/events/75.en.html ● www.postgresql.orgで使われているコードは pgweb.postgresql.orgで公開されている ● https://pgweb.postgresql.org/browser/trunk/portal/tools/search 09/06/20
  36. 36. ● Some recent advences in full-text search(PGcon 2009) ● http://www.pgcon.org/2009/schedule/events/119.en.html ● 8.4での新機能 – 前方一致検索等 ● 8.5以降で実装予定の機能等 – フレーズ検索等 09/06/20

×