fts_lite 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # FtsLite
2
2
 
3
- full text search index.
3
+ FtsLiteは組み込み型お手軽全文検索エンジンのRubyライブラリです。
4
+ 基本的にはSQLite3 FTS4のラッパーで、日本語のbigramやtrigram、wakachi_bigramなどのトークナイザーをRubyのレイヤで実装したものです。
5
+
6
+ qarc.info で使われています。
7
+
8
+ Ruby 1.9.2 以降と、FTS4 に対応してる SQLite3 が必要で、SQLite3 はできれば 3.7.7 以降がよいです(FTS4の仮想テーブルに対するINSERT OR REPLACEが実装されているのでsetのパフォーマンスがよい)。
4
9
 
5
10
  ## Installation
6
11
 
@@ -18,4 +23,69 @@ Or install it yourself as:
18
23
 
19
24
  ## Usage
20
25
 
21
- TODO
26
+ # -*- coding: utf-8 -*-
27
+ require 'fts_lite'
28
+
29
+ FtsLite::Index.open("./index.sqlite3") do |db|
30
+ # set(docid, text, sort_value = nil)
31
+ db.set(1, "なぜナポリタンは赤いのだろうか?")
32
+ db.set(2, "昼飯のスパゲティナポリタンを眺めながら、積年の疑問を考えていた。")
33
+
34
+ # docid_array = search(query, options = {})
35
+ docids = db.search("ナポリタン")
36
+ puts docids.join(",")
37
+
38
+ docids = db.search("赤い ナポリタン")
39
+ puts docids.join(",")
40
+
41
+ # update_sort_value(docid, sort_value)
42
+ db.update_sort_value(1, 2)
43
+ db.update_sort_value(2, 1)
44
+
45
+ docids = db.search("ナポリタン", :order => :asc, :limit => 1)
46
+ puts docids.join(",")
47
+ end
48
+
49
+ set(docid, text, sort\_value)でデータを登録します。
50
+ docidはレコードを表すIDで search ではこのIDの配列を検索結果として返します。
51
+ textは全文検索インデックスのためのテキストデータです。取り出すことはできないので、元のデータは別のデータベースにあることを想定しています。
52
+ sort\_valueはソート用の値で、searchの時にこの値でソートしたり、ソートしたうえで上位N件を取り出したりできます。
53
+
54
+ search(query, options) で検索できて、queryは空白区切りでAND検索です。このへんの仕様は用途によっていろいろだと思うけど、僕はテキトウにANDだけできればいいやと思っているので、いじりたい人は lib/tokenizer.rb の各トークナイザで定義してある query というメソッドをいじってください。
55
+ optionsは :order に :desc か :asc を指定すると sort\_value で昇順ソートまたは降順ソートします。 :order が指定されない場合は docid の昇順になります。:limit => N を指定すると検索結果の上位N件だけを返します。
56
+
57
+ ## Railsで使う
58
+
59
+ まず config/application.rb あたりで
60
+
61
+ QUESTION_FTS = FtsLite::Index.open(File.join(Rails.root.to_s, "fts", "index.sqlite3"), :table_name => "questions")
62
+ THREAD_FTS = FtsLite::Index.open(File.join(Rails.root.to_s, "fts", "index.sqlite3"), :table_name => "threads")
63
+ # ...
64
+
65
+ とコネクションを作ってグローバルにアクセスできるようにしておきます。
66
+ モデルでしか使わない場合は、モデルの中で定義したほうがいいかもしれません。
67
+ :table\_name を指定するとひとつのDBファイルに複数の全文検索インデックスが持てます。
68
+
69
+ あとは、たとえば、Question という ActiveRecord のモデルがあって、全文検索用のテキストデータ(内容やタイトルなんかを適当に結合した文字列)を作成する make\_ft というメソッドとソート用の表示数 view_count というカラムがあるとすると
70
+
71
+ class Question < ActiveRecord::Base
72
+ LIMIT = 1000
73
+ after_save :set_ft
74
+
75
+ def set_ft
76
+ QUESTION_FTS.set(id, make_ft, view_count)
77
+ end
78
+ def search(query)
79
+ find(:all,
80
+ :conditions => ["id in (?)", QUESTION_FTS.search(query, :order => :desc, :limit => LIMIT)],
81
+ :order => "view_count DESC")
82
+ end
83
+ # def make_ft ...
84
+ end
85
+
86
+ まず after\_save でレコードの更新時に全文検索インデックス側も更新するようにしておきます。
87
+ search というメソットでは、全文検索を行って、その結果(IDの配列)を含むレコードをさらにDBに問い合わせることで検索結果となるレコードを返しています。
88
+
89
+ この実装だとレプリケーションしている場合に、別のサーバーでレコードが更新されるとトリガーが効かなくてローカルの全文検索インデックスが更新されないことに注意してください。
90
+ そういう場合は、定期ジョブで適当に同期すればいいと思います。
91
+
@@ -6,6 +6,7 @@ module FtsLite
6
6
  DEFAULT_JURNAL_MODE = "MEMORY"
7
7
  DEFAULT_TEMP_STORE = "MEMORY"
8
8
  DEFAULT_CACHE_SIZE = 32000
9
+ DEFAULT_TIMEOUT = 10000
9
10
  SQLITE_HAVE_FT4_REPLACE = SQLite3.libversion >= 3007007
10
11
 
11
12
  def self.have_ft4_replace
@@ -127,6 +128,7 @@ module FtsLite
127
128
  @db.execute("PRAGMA journal_mode=#{options[:journal_mode] || DEFAULT_JURNAL_MODE};")
128
129
  @db.execute("PRAGMA temp_store=#{options[:temp_store] || DEFAULT_TEMP_STORE};")
129
130
  @db.execute("PRAGMA cache_size=#{options[:cache_size] || DEFAULT_CACHE_SIZE};")
131
+ @db.busy_timeout = options[:timeout] || DEFAULT_TIMEOUT
130
132
  end
131
133
  end
132
134
  end
@@ -1,3 +1,3 @@
1
1
  module FtsLite
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fts_lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-05 00:00:00.000000000 Z
12
+ date: 2012-08-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bimyou_segmenter