xapian_db 0.5.5 → 0.5.6

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 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:
@@ -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 (10) How many docs 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 = {:per_page => 10, :sort_decending => false}.merge(options)
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 accessor for the indexed class
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
@@ -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
- @enquiry = enquiry
45
- return build_empty_resultset if @enquiry.nil?
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
- @hits = enquiry.mset(0, db_size).matches_estimated
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 = @enquiry.mset(offset, count)
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 document with field accessors for each configured attribute
92
- def decorate(document)
93
- klass_name = document.values[0].value
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
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-25 00:00:00 +01:00
13
+ date: 2011-02-28 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency