xapian_db 0.5.3 → 0.5.4
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/CHANGELOG.md +12 -0
- data/README.rdoc +10 -10
- data/lib/xapian_db/adapters/base_adapter.rb +4 -3
- data/lib/xapian_db/database.rb +8 -4
- data/lib/xapian_db/query_parser.rb +1 -0
- data/lib/xapian_db/railtie.rb +2 -2
- data/lib/xapian_db/resultset.rb +36 -34
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
##0.5.4 (February 22th, 2011)
|
2
|
+
|
3
|
+
Fixes:
|
4
|
+
|
5
|
+
- relative database paths in the config file are resolved correctly when the Rails server is started as a daemon (-d)
|
6
|
+
|
7
|
+
Breaking Changes:
|
8
|
+
|
9
|
+
- the spelling suggestion of a query is now nil instead of an empty string if no suggestions were returned from xapian
|
10
|
+
- the resultset class (what you get back from a query) has been refactored for easier handling. See the README ("Process the results")
|
11
|
+
for details
|
12
|
+
|
1
13
|
##0.5.3 (February 15th, 2011)
|
2
14
|
|
3
15
|
Fixes:
|
data/README.rdoc
CHANGED
@@ -149,22 +149,27 @@ You can query objects of a specific class:
|
|
149
149
|
|
150
150
|
results = Person.search "name:Foo"
|
151
151
|
|
152
|
-
If you want to
|
152
|
+
If you want to paginate the result, pass the :per_page argument:
|
153
153
|
|
154
154
|
results = Person.search "name:Foo", :per_page => 20
|
155
155
|
|
156
|
+
If you want to limit the number of results, pass the :limit argument (handy if you use the query for autocompletion):
|
157
|
+
|
158
|
+
results = Person.search "name:Foo", :limit => 10
|
159
|
+
|
156
160
|
On class queries you can specifiy order options:
|
157
161
|
|
158
162
|
results = Person.search "name:Foo", :order => :first_name
|
159
163
|
results = Person.search "Fo*", :order => [:name, :first_name], :sort_decending => true
|
160
164
|
|
161
|
-
Please note that the order option is not
|
165
|
+
Please note that the order option is not available for global searches (XapianDb.search...)
|
162
166
|
|
163
167
|
=== Process the results
|
164
168
|
|
165
169
|
<code>XapianDb.search</code> returns a resultset object. You can access the number of hits directly:
|
166
170
|
|
167
|
-
results.
|
171
|
+
results.hits # Very fast, does not load the resulting documents; always returns the actual hit count
|
172
|
+
# even if a limit option was set in the query
|
168
173
|
|
169
174
|
If you use a persistent database, the resultset may contain a spelling correction:
|
170
175
|
|
@@ -172,14 +177,9 @@ If you use a persistent database, the resultset may contain a spelling correctio
|
|
172
177
|
results = XapianDb.search("moose")
|
173
178
|
results.spelling_suggestion # "mouse"
|
174
179
|
|
175
|
-
|
176
|
-
|
177
|
-
page = results.paginate # Get the first page
|
178
|
-
page = results.paginate :page => 2 # Get the second page
|
179
|
-
|
180
|
-
Now you can access the documents:
|
180
|
+
The results behave like an array:
|
181
181
|
|
182
|
-
doc =
|
182
|
+
doc = results.first
|
183
183
|
puts doc.indexed_class # Get the type of the indexed object as a string, e.g. "Person"
|
184
184
|
puts doc.name # We can access the configured attributes
|
185
185
|
person = doc.indexed_object # Access the object behind this doc (lazy loaded)
|
@@ -30,8 +30,9 @@ module XapianDb
|
|
30
30
|
options = {:sort_decending => false}.merge options
|
31
31
|
class_scope = "indexed_class:#{klass.name.downcase}"
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
order = options.delete :order
|
34
|
+
if order
|
35
|
+
attr_names = [order].flatten
|
35
36
|
blueprint = XapianDb::DocumentBlueprint.blueprint_for klass
|
36
37
|
sort_indices = attr_names.map {|attr_name| blueprint.value_index_for(attr_name)}
|
37
38
|
options[:sort_indices] = attr_names.map {|attr_name| blueprint.value_index_for(attr_name)}
|
@@ -39,7 +40,7 @@ module XapianDb
|
|
39
40
|
result = XapianDb.database.search "#{class_scope} and (#{expression})", options
|
40
41
|
|
41
42
|
# Remove the class scope from the spelling suggestion (if any)
|
42
|
-
|
43
|
+
if result.spelling_suggestion
|
43
44
|
scope_length = "#{class_scope} and (".size
|
44
45
|
result.spelling_suggestion = result.spelling_suggestion.slice scope_length..-2
|
45
46
|
end
|
data/lib/xapian_db/database.rb
CHANGED
@@ -67,13 +67,17 @@ module XapianDb
|
|
67
67
|
|
68
68
|
Rails.logger.info "Executing XapianDb search: #{expression}" if defined?(Rails)
|
69
69
|
|
70
|
-
enquiry
|
71
|
-
enquiry.query
|
72
|
-
|
70
|
+
enquiry = Xapian::Enquire.new(reader)
|
71
|
+
enquiry.query = query
|
72
|
+
sort_indices = opts.delete :sort_indices
|
73
|
+
sort_decending = opts.delete :sort_decending
|
74
|
+
|
75
|
+
if sort_indices
|
73
76
|
raise ArgumentError.new("Sorting is available for class scoped searches only") unless expression =~ /^indexed_class:/
|
74
77
|
sorter = Xapian::MultiValueSorter.new
|
78
|
+
|
75
79
|
options[:sort_indices].each do |index|
|
76
|
-
sorter.add(index,
|
80
|
+
sorter.add(index, sort_decending)
|
77
81
|
end
|
78
82
|
enquiry.set_sort_by_key_then_relevance(sorter)
|
79
83
|
end
|
@@ -41,6 +41,7 @@ module XapianDb
|
|
41
41
|
XapianDb::DocumentBlueprint.searchable_prefixes.each{|prefix| parser.add_prefix(prefix.to_s.downcase, "X#{prefix.to_s.upcase}") }
|
42
42
|
query = parser.parse_query(expression, @query_flags)
|
43
43
|
@spelling_suggestion = parser.get_corrected_query_string
|
44
|
+
@spelling_suggestion = nil if @spelling_suggestion.empty?
|
44
45
|
query
|
45
46
|
end
|
46
47
|
|
data/lib/xapian_db/railtie.rb
CHANGED
@@ -21,13 +21,13 @@ module XapianDb
|
|
21
21
|
if File.exist?(config_file_path)
|
22
22
|
db_config = YAML::load_file config_file_path
|
23
23
|
env_config = db_config[Rails.env]
|
24
|
-
database_path = env_config["database"] || ":memory:"
|
24
|
+
database_path = File.expand_path(env_config["database"]) || ":memory:"
|
25
25
|
adapter = env_config["adapter"] || :active_record
|
26
26
|
writer = env_config["writer"] || :direct
|
27
27
|
beanstalk_daemon = env_config["beanstalk_daemon"]
|
28
28
|
else
|
29
29
|
# No config file, set the defaults
|
30
|
-
Rails.env == "test" ? database_path = ":memory:" : database_path = "db/xapian_db/#{Rails.env}"
|
30
|
+
Rails.env == "test" ? database_path = ":memory:" : database_path = File.expand_path("db/xapian_db/#{Rails.env}")
|
31
31
|
adapter = :active_record
|
32
32
|
writer = :direct
|
33
33
|
beanstalk_daemon = nil
|
data/lib/xapian_db/resultset.rb
CHANGED
@@ -12,11 +12,11 @@ module XapianDb
|
|
12
12
|
# @example Use the resultset and will_paginate in a view
|
13
13
|
# <%= will_paginate resultset %>
|
14
14
|
# @author Gernot Kogler
|
15
|
-
class Resultset
|
15
|
+
class Resultset < Array
|
16
16
|
|
17
|
-
# The number of
|
17
|
+
# The number of hits
|
18
18
|
# @return [Integer]
|
19
|
-
attr_reader :
|
19
|
+
attr_reader :hits
|
20
20
|
|
21
21
|
# The number of pages
|
22
22
|
# @return [Integer]
|
@@ -34,29 +34,36 @@ module XapianDb
|
|
34
34
|
# @param [Xapian::Enquire] enquiry a Xapian query result (see http://xapian.org/docs/apidoc/html/classXapian_1_1Enquire.html).
|
35
35
|
# Pass nil to get an empty result set.
|
36
36
|
# @param [Hash] options
|
37
|
-
# @option options [Integer] :
|
37
|
+
# @option options [Integer] :db_size The current size (nr of docs) of the database
|
38
|
+
# @option options [Integer] :limit The maximum number of documents to retrieve
|
39
|
+
# @option options [Integer] :page (1) The page number to retrieve
|
40
|
+
# @option options [Integer] :per_page (10) How many docs per page? Ignored if a limit option is given
|
38
41
|
# @option options [String] :spelling_suggestion (nil) The spelling corrected query (if a language is configured)
|
39
|
-
def initialize(enquiry, options)
|
42
|
+
def initialize(enquiry, options={})
|
43
|
+
|
40
44
|
@enquiry = enquiry
|
41
|
-
if @enquiry.nil?
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
@spelling_suggestion = options
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
return build_empty_resultset if @enquiry.nil?
|
46
|
+
|
47
|
+
db_size = options.delete :db_size
|
48
|
+
limit = options.delete :limit
|
49
|
+
page = options.delete :page
|
50
|
+
per_page = options.delete :per_page
|
51
|
+
@spelling_suggestion = options.delete :spelling_suggestion
|
52
|
+
raise ArgumentError.new "unsupported options for resultset: #{options}" if options.size > 0
|
53
|
+
raise ArgumentError.new "db_size option is required" unless db_size
|
54
|
+
|
55
|
+
@hits = enquiry.mset(0, db_size).matches_estimated
|
56
|
+
limit ||= @hits
|
57
|
+
per_page ||= limit
|
58
|
+
@total_pages = (limit / per_page.to_f).ceil
|
59
|
+
page = page.nil? ? 1 : page.to_i
|
60
|
+
offset = (page - 1) * per_page
|
61
|
+
count = offset + per_page < limit ? per_page : limit - offset
|
62
|
+
raise ArgumentError.new "page #{@page} does not exist" if @hits > 0 && offset >= limit
|
52
63
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
def paginate(options={})
|
57
|
-
@current_page = options[:page] ? options[:page].to_i : 1
|
58
|
-
return [] if @current_page < 1 || @current_page > @total_pages
|
59
|
-
build_page(@current_page)
|
64
|
+
result_window = @enquiry.mset(offset, count)
|
65
|
+
self.replace result_window.matches.map{|match| decorate(match.document)}
|
66
|
+
@current_page = page
|
60
67
|
end
|
61
68
|
|
62
69
|
# The previous page number
|
@@ -73,17 +80,12 @@ module XapianDb
|
|
73
80
|
|
74
81
|
private
|
75
82
|
|
76
|
-
# Build
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
result_window = @enquiry.mset(offset, @per_page)
|
83
|
-
result_window.matches.each do |match|
|
84
|
-
docs << decorate(match.document)
|
85
|
-
end
|
86
|
-
docs
|
83
|
+
# Build an empty resultset
|
84
|
+
def build_empty_resultset
|
85
|
+
@hits = 0
|
86
|
+
@total_pages = 0
|
87
|
+
@current_page = 0
|
88
|
+
self
|
87
89
|
end
|
88
90
|
|
89
91
|
# Decorate a Xapian document with field accessors for each configured attribute
|
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.4
|
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-22 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|