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 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