/
xapian_fu.rb
80 lines (69 loc) · 1.78 KB
/
xapian_fu.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
require 'xapian'
class XapianDb
include Xapian
attr_reader :dir, :db_flag, :query_parser
def initialize( options )
@dir = options[:dir]
@db_flag = DB_OPEN
@db_flag = DB_CREATE_OR_OPEN if options[:create]
@db_flag = DB_CREATE_OR_OVERWRITE if options[:overwrite]
end
def db
@db ||= WritableDatabase.new(dir, db_flag)
end
def <<(doc)
xdoc = Document.new
xdoc.data = Marshal.dump(doc.data) if doc.data
tg = TermGenerator.new
tg.database = db
tg.document = xdoc
tg.index_text( doc.fields.keys.collect{|k|doc.fields[k]}.join(' ') )
db.add_document(xdoc)
end
def search(q, options = {})
defaults = { :offset => 0, :limit => 10 }
options = defaults.merge(options)
query = query_parser.parse_query(q, QueryParser::FLAG_WILDCARD && QueryParser::FLAG_LOVEHATE)
enquiry.query = query
enquiry.mset(options[:offset], options[:limit]).matches.collect { |m| XapianResult.new(m) }
end
def transaction
db.begin_transaction
yield
db.commit_transaction
rescue Exception => e
db.cancel_transaction
raise e
end
def flush
db.flush
end
def query_parser
unless @query_parser
@query_parser = QueryParser.new
@query_parser.database = db
end
@query_parser
end
def enquiry
@enquiry ||= Enquire.new(db)
end
end
class XapianDoc
attr_reader :fields, :data
def initialize(fields, options = {})
@fields = fields
@weight = options[:weight] if options[:weight]
@data = options[:data] if options[:data]
end
end
class XapianResult
attr_reader :score, :percent, :doc, :data, :id
def initialize(match)
@score = match.weight
@percent = match.percent
@doc = match.document
@id = @doc.docid
@data = Marshal.load(@doc.data) unless @doc.data.empty?
end
end