fts_lite 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +72 -2
- data/lib/fts_lite/index.rb +2 -0
- data/lib/fts_lite/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# FtsLite
|
2
2
|
|
3
|
-
|
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
|
-
|
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
|
+
|
data/lib/fts_lite/index.rb
CHANGED
@@ -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
|
data/lib/fts_lite/version.rb
CHANGED
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.
|
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-
|
12
|
+
date: 2012-08-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bimyou_segmenter
|