xapian_db 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +8 -0
- data/README.rdoc +9 -0
- data/lib/xapian_db/database.rb +2 -2
- data/lib/xapian_db/document_blueprint.rb +7 -1
- data/lib/xapian_db/query_parser.rb +1 -0
- data/lib/xapian_db/resultset.rb +26 -12
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
##0.5.6 (February 28th, 2011)
|
2
|
+
|
3
|
+
Features:
|
4
|
+
|
5
|
+
- documents returned by a query have the new score property that reflects the match relevance in percent (1-100%)
|
6
|
+
- added compatibility to the kaminari pagination gem (thanks, Javi)
|
7
|
+
- added support for phrase searches (XapianDb.search('"this exact sentence"'))
|
8
|
+
|
1
9
|
##0.5.5 (February 25th, 2011)
|
2
10
|
|
3
11
|
Fixes:
|
data/README.rdoc
CHANGED
@@ -155,6 +155,10 @@ You can query objects of a specific class:
|
|
155
155
|
|
156
156
|
results = Person.search "name:Foo"
|
157
157
|
|
158
|
+
You can search for exact phrases:
|
159
|
+
|
160
|
+
results = XapianDb.search('"this exact sentence"')
|
161
|
+
|
158
162
|
If you want to paginate the result, pass the :per_page argument:
|
159
163
|
|
160
164
|
results = Person.search "name:Foo", :per_page => 20
|
@@ -186,6 +190,7 @@ If you use a persistent database, the resultset may contain a spelling correctio
|
|
186
190
|
The results behave like an array:
|
187
191
|
|
188
192
|
doc = results.first
|
193
|
+
puts doc.score.to_s # Get the relevance of the document
|
189
194
|
puts doc.indexed_class # Get the type of the indexed object as a string, e.g. "Person"
|
190
195
|
puts doc.name # We can access the configured attributes
|
191
196
|
person = doc.indexed_object # Access the object behind this doc (lazy loaded)
|
@@ -194,6 +199,10 @@ Use a search result with will_paginate in a view:
|
|
194
199
|
|
195
200
|
<%= will_paginate @results %>
|
196
201
|
|
202
|
+
Or with kaminari:
|
203
|
+
|
204
|
+
<%= kaminari @results %>
|
205
|
+
|
197
206
|
=== Facets
|
198
207
|
|
199
208
|
If you want to implement a simple drilldown for your searches, you can use a global facets query:
|
data/lib/xapian_db/database.rb
CHANGED
@@ -43,7 +43,7 @@ module XapianDb
|
|
43
43
|
# Perform a search
|
44
44
|
# @param [String] expression A valid search expression.
|
45
45
|
# @param [Hash] options
|
46
|
-
# @option options [Integer] :per_page
|
46
|
+
# @option options [Integer] :per_page How many docs per page?
|
47
47
|
# @option options [Array<Integer>] :sort_indices (nil) An array of attribute indices to sort by. This
|
48
48
|
# option is used internally by the search method implemented on configured classes. Do not use it
|
49
49
|
# directly unless
|
@@ -58,7 +58,7 @@ module XapianDb
|
|
58
58
|
# resultset = db.search("name:foo")
|
59
59
|
# @return [XapianDb::Resultset] The resultset
|
60
60
|
def search(expression, options={})
|
61
|
-
opts = {:
|
61
|
+
opts = {:sort_decending => false}.merge(options)
|
62
62
|
@query_parser ||= QueryParser.new(self)
|
63
63
|
query = @query_parser.parse(expression)
|
64
64
|
|
@@ -142,11 +142,17 @@ module XapianDb
|
|
142
142
|
return @accessors_module unless @accessors_module.nil?
|
143
143
|
@accessors_module = Module.new
|
144
144
|
|
145
|
-
# Add the
|
145
|
+
# Add the accessors for the indexed class and the score
|
146
146
|
@accessors_module.instance_eval do
|
147
|
+
|
147
148
|
define_method :indexed_class do
|
148
149
|
self.values[0].value
|
149
150
|
end
|
151
|
+
|
152
|
+
define_method :score do
|
153
|
+
@score
|
154
|
+
end
|
155
|
+
|
150
156
|
end
|
151
157
|
|
152
158
|
# Add an accessor for each attribute
|
@@ -21,6 +21,7 @@ module XapianDb
|
|
21
21
|
@query_flags |= Xapian::QueryParser::FLAG_BOOLEAN # enable boolean operators
|
22
22
|
@query_flags |= Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE # enable case insensitive boolean operators
|
23
23
|
@query_flags |= Xapian::QueryParser::FLAG_SPELLING_CORRECTION # enable spelling corrections
|
24
|
+
@query_flags |= Xapian::QueryParser::FLAG_PHRASE # enable phrase searches
|
24
25
|
end
|
25
26
|
|
26
27
|
# Parse an expression
|
data/lib/xapian_db/resultset.rb
CHANGED
@@ -4,23 +4,27 @@ module XapianDb
|
|
4
4
|
|
5
5
|
# The resultset encapsulates a Xapian::Query object and allows paged access
|
6
6
|
# to the found documents.
|
7
|
-
# The resultset is compatible with will_paginate.
|
7
|
+
# The resultset is compatible with will_paginate and kaminari.
|
8
8
|
# @example Process the first page of a resultsest
|
9
9
|
# resultset.paginate(:page => 1, :per_page => 10).each do |doc|
|
10
10
|
# # do something with the xapian document
|
11
11
|
# end
|
12
12
|
# @example Use the resultset and will_paginate in a view
|
13
13
|
# <%= will_paginate resultset %>
|
14
|
+
# @example Use the resultset and kaminari in a view
|
15
|
+
# <%= paginate resultset %>
|
14
16
|
# @author Gernot Kogler
|
15
17
|
class Resultset < Array
|
16
18
|
|
17
19
|
# The number of hits
|
18
20
|
# @return [Integer]
|
19
21
|
attr_reader :hits
|
22
|
+
alias_method :total_count, :hits
|
20
23
|
|
21
24
|
# The number of pages
|
22
25
|
# @return [Integer]
|
23
26
|
attr_reader :total_pages
|
27
|
+
alias_method :num_pages, :total_pages
|
24
28
|
|
25
29
|
# The current page
|
26
30
|
# @return [Integer]
|
@@ -30,6 +34,9 @@ module XapianDb
|
|
30
34
|
# @return [String]
|
31
35
|
attr_accessor :spelling_suggestion
|
32
36
|
|
37
|
+
# The number of records per page
|
38
|
+
attr_reader :limit_value
|
39
|
+
|
33
40
|
# Constructor
|
34
41
|
# @param [Xapian::Enquire] enquiry a Xapian query result (see http://xapian.org/docs/apidoc/html/classXapian_1_1Enquire.html).
|
35
42
|
# Pass nil to get an empty result set.
|
@@ -41,18 +48,20 @@ module XapianDb
|
|
41
48
|
# @option options [String] :spelling_suggestion (nil) The spelling corrected query (if a language is configured)
|
42
49
|
def initialize(enquiry, options={})
|
43
50
|
|
44
|
-
|
45
|
-
return build_empty_resultset if
|
46
|
-
|
51
|
+
enquiry = enquiry
|
52
|
+
return build_empty_resultset if enquiry.nil?
|
47
53
|
db_size = options.delete :db_size
|
54
|
+
@spelling_suggestion = options.delete :spelling_suggestion
|
55
|
+
@hits = enquiry.mset(0, db_size).matches_estimated
|
56
|
+
return build_empty_resultset if @hits == 0
|
57
|
+
|
48
58
|
limit = options.delete :limit
|
49
59
|
page = options.delete :page
|
50
60
|
per_page = options.delete :per_page
|
51
|
-
@spelling_suggestion = options.delete :spelling_suggestion
|
52
61
|
raise ArgumentError.new "unsupported options for resultset: #{options}" if options.size > 0
|
53
62
|
raise ArgumentError.new "db_size option is required" unless db_size
|
54
63
|
|
55
|
-
|
64
|
+
|
56
65
|
limit ||= @hits
|
57
66
|
per_page ||= limit
|
58
67
|
@total_pages = (limit / per_page.to_f).ceil
|
@@ -61,9 +70,10 @@ module XapianDb
|
|
61
70
|
count = offset + per_page < limit ? per_page : limit - offset
|
62
71
|
raise ArgumentError.new "page #{@page} does not exist" if @hits > 0 && offset >= limit
|
63
72
|
|
64
|
-
result_window =
|
65
|
-
self.replace result_window.matches.map{|match| decorate(match.document
|
73
|
+
result_window = enquiry.mset(offset, count)
|
74
|
+
self.replace result_window.matches.map{|match| decorate(match).document}
|
66
75
|
@current_page = page
|
76
|
+
@limit_value = per_page
|
67
77
|
end
|
68
78
|
|
69
79
|
# The previous page number
|
@@ -88,11 +98,15 @@ module XapianDb
|
|
88
98
|
self
|
89
99
|
end
|
90
100
|
|
91
|
-
# Decorate a Xapian
|
92
|
-
|
93
|
-
|
101
|
+
# Decorate a Xapian match with field accessors for each configured attribute
|
102
|
+
# @param [Xapian::Match] a match
|
103
|
+
# @return [Xapian::Match] the decorated match
|
104
|
+
def decorate(match)
|
105
|
+
klass_name = match.document.values[0].value
|
94
106
|
blueprint = XapianDb::DocumentBlueprint.blueprint_for(Kernel.const_get(klass_name))
|
95
|
-
document.extend blueprint.accessors_module
|
107
|
+
match.document.extend blueprint.accessors_module
|
108
|
+
match.document.instance_variable_set :@score, match.percent
|
109
|
+
match
|
96
110
|
end
|
97
111
|
|
98
112
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: xapian_db
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.5.
|
5
|
+
version: 0.5.6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Gernot Kogler
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-02-
|
13
|
+
date: 2011-02-28 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|