sunspot 2.0.0 → 2.5.0

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.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/Appraisals +7 -0
  5. data/Gemfile +0 -2
  6. data/History.txt +10 -0
  7. data/lib/sunspot.rb +55 -17
  8. data/lib/sunspot/adapters.rb +68 -18
  9. data/lib/sunspot/batcher.rb +1 -1
  10. data/lib/sunspot/configuration.rb +4 -2
  11. data/lib/sunspot/data_extractor.rb +36 -6
  12. data/lib/sunspot/dsl.rb +4 -3
  13. data/lib/sunspot/dsl/adjustable.rb +2 -2
  14. data/lib/sunspot/dsl/field_query.rb +69 -16
  15. data/lib/sunspot/dsl/field_stats.rb +25 -0
  16. data/lib/sunspot/dsl/fields.rb +28 -8
  17. data/lib/sunspot/dsl/fulltext.rb +9 -1
  18. data/lib/sunspot/dsl/group.rb +118 -0
  19. data/lib/sunspot/dsl/paginatable.rb +4 -1
  20. data/lib/sunspot/dsl/scope.rb +19 -10
  21. data/lib/sunspot/dsl/search.rb +1 -1
  22. data/lib/sunspot/dsl/spellcheckable.rb +14 -0
  23. data/lib/sunspot/dsl/standard_query.rb +63 -35
  24. data/lib/sunspot/field.rb +76 -4
  25. data/lib/sunspot/field_factory.rb +60 -11
  26. data/lib/sunspot/indexer.rb +70 -18
  27. data/lib/sunspot/query.rb +5 -4
  28. data/lib/sunspot/query/abstract_field_facet.rb +0 -2
  29. data/lib/sunspot/query/abstract_fulltext.rb +76 -0
  30. data/lib/sunspot/query/abstract_json_field_facet.rb +70 -0
  31. data/lib/sunspot/query/bbox.rb +5 -1
  32. data/lib/sunspot/query/common_query.rb +31 -6
  33. data/lib/sunspot/query/composite_fulltext.rb +58 -8
  34. data/lib/sunspot/query/date_field_json_facet.rb +25 -0
  35. data/lib/sunspot/query/dismax.rb +25 -71
  36. data/lib/sunspot/query/field_json_facet.rb +19 -0
  37. data/lib/sunspot/query/field_list.rb +15 -0
  38. data/lib/sunspot/query/field_stats.rb +61 -0
  39. data/lib/sunspot/query/function_query.rb +1 -2
  40. data/lib/sunspot/query/geo.rb +1 -1
  41. data/lib/sunspot/query/geofilt.rb +8 -3
  42. data/lib/sunspot/query/group.rb +46 -0
  43. data/lib/sunspot/query/group_query.rb +17 -0
  44. data/lib/sunspot/query/join.rb +88 -0
  45. data/lib/sunspot/query/more_like_this.rb +1 -1
  46. data/lib/sunspot/query/pagination.rb +12 -4
  47. data/lib/sunspot/query/range_json_facet.rb +28 -0
  48. data/lib/sunspot/query/restriction.rb +99 -13
  49. data/lib/sunspot/query/sort.rb +41 -0
  50. data/lib/sunspot/query/sort_composite.rb +7 -0
  51. data/lib/sunspot/query/spellcheck.rb +19 -0
  52. data/lib/sunspot/query/standard_query.rb +24 -2
  53. data/lib/sunspot/query/text_field_boost.rb +1 -3
  54. data/lib/sunspot/schema.rb +12 -3
  55. data/lib/sunspot/search.rb +4 -2
  56. data/lib/sunspot/search/abstract_search.rb +93 -43
  57. data/lib/sunspot/search/cursor_paginated_collection.rb +32 -0
  58. data/lib/sunspot/search/field_facet.rb +4 -4
  59. data/lib/sunspot/search/field_json_facet.rb +33 -0
  60. data/lib/sunspot/search/field_stats.rb +21 -0
  61. data/lib/sunspot/search/hit.rb +6 -1
  62. data/lib/sunspot/search/hit_enumerable.rb +4 -1
  63. data/lib/sunspot/search/json_facet_row.rb +40 -0
  64. data/lib/sunspot/search/json_facet_stats.rb +23 -0
  65. data/lib/sunspot/search/paginated_collection.rb +1 -0
  66. data/lib/sunspot/search/query_group.rb +74 -0
  67. data/lib/sunspot/search/standard_search.rb +70 -3
  68. data/lib/sunspot/search/stats_facet.rb +25 -0
  69. data/lib/sunspot/search/stats_json_row.rb +82 -0
  70. data/lib/sunspot/search/stats_row.rb +68 -0
  71. data/lib/sunspot/session.rb +62 -37
  72. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +6 -4
  73. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +16 -8
  74. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +2 -2
  75. data/lib/sunspot/session_proxy/retry_5xx_session_proxy.rb +1 -1
  76. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +4 -2
  77. data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +1 -1
  78. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +6 -4
  79. data/lib/sunspot/setup.rb +42 -0
  80. data/lib/sunspot/type.rb +20 -0
  81. data/lib/sunspot/util.rb +78 -14
  82. data/lib/sunspot/version.rb +1 -1
  83. data/spec/api/adapters_spec.rb +40 -15
  84. data/spec/api/batcher_spec.rb +15 -15
  85. data/spec/api/binding_spec.rb +3 -3
  86. data/spec/api/class_set_spec.rb +6 -6
  87. data/spec/api/data_extractor_spec.rb +39 -0
  88. data/spec/api/hit_enumerable_spec.rb +32 -9
  89. data/spec/api/indexer/attributes_spec.rb +35 -30
  90. data/spec/api/indexer/batch_spec.rb +8 -7
  91. data/spec/api/indexer/dynamic_fields_spec.rb +8 -8
  92. data/spec/api/indexer/fixed_fields_spec.rb +16 -11
  93. data/spec/api/indexer/fulltext_spec.rb +8 -8
  94. data/spec/api/indexer/removal_spec.rb +24 -14
  95. data/spec/api/indexer_spec.rb +2 -2
  96. data/spec/api/query/advanced_manipulation_examples.rb +3 -3
  97. data/spec/api/query/connectives_examples.rb +26 -14
  98. data/spec/api/query/dsl_spec.rb +24 -6
  99. data/spec/api/query/dynamic_fields_examples.rb +18 -18
  100. data/spec/api/query/faceting_examples.rb +80 -61
  101. data/spec/api/query/fulltext_examples.rb +194 -40
  102. data/spec/api/query/function_spec.rb +116 -13
  103. data/spec/api/query/geo_examples.rb +8 -12
  104. data/spec/api/query/group_spec.rb +27 -5
  105. data/spec/api/query/highlighting_examples.rb +26 -26
  106. data/spec/api/query/join_spec.rb +19 -0
  107. data/spec/api/query/more_like_this_spec.rb +40 -27
  108. data/spec/api/query/ordering_pagination_examples.rb +37 -23
  109. data/spec/api/query/scope_examples.rb +39 -39
  110. data/spec/api/query/spatial_examples.rb +3 -3
  111. data/spec/api/query/spellcheck_examples.rb +20 -0
  112. data/spec/api/query/standard_spec.rb +3 -1
  113. data/spec/api/query/stats_examples.rb +66 -0
  114. data/spec/api/query/text_field_scoping_examples.rb +5 -5
  115. data/spec/api/query/types_spec.rb +4 -4
  116. data/spec/api/search/cursor_paginated_collection_spec.rb +35 -0
  117. data/spec/api/search/dynamic_fields_spec.rb +4 -4
  118. data/spec/api/search/faceting_spec.rb +55 -52
  119. data/spec/api/search/highlighting_spec.rb +7 -7
  120. data/spec/api/search/hits_spec.rb +43 -29
  121. data/spec/api/search/paginated_collection_spec.rb +19 -18
  122. data/spec/api/search/results_spec.rb +13 -13
  123. data/spec/api/search/search_spec.rb +3 -3
  124. data/spec/api/search/stats_spec.rb +94 -0
  125. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +23 -16
  126. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +16 -4
  127. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +10 -6
  128. data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +11 -11
  129. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +15 -14
  130. data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +3 -3
  131. data/spec/api/session_proxy/spec_helper.rb +1 -1
  132. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +40 -26
  133. data/spec/api/session_spec.rb +78 -38
  134. data/spec/api/sunspot_spec.rb +7 -4
  135. data/spec/helpers/integration_helper.rb +11 -1
  136. data/spec/helpers/query_helper.rb +1 -1
  137. data/spec/helpers/search_helper.rb +30 -0
  138. data/spec/integration/atomic_updates_spec.rb +58 -0
  139. data/spec/integration/dynamic_fields_spec.rb +31 -20
  140. data/spec/integration/faceting_spec.rb +252 -39
  141. data/spec/integration/field_grouping_spec.rb +47 -15
  142. data/spec/integration/field_lists_spec.rb +57 -0
  143. data/spec/integration/geospatial_spec.rb +34 -8
  144. data/spec/integration/highlighting_spec.rb +8 -8
  145. data/spec/integration/indexing_spec.rb +7 -6
  146. data/spec/integration/join_spec.rb +45 -0
  147. data/spec/integration/keyword_search_spec.rb +68 -38
  148. data/spec/integration/local_search_spec.rb +4 -4
  149. data/spec/integration/more_like_this_spec.rb +7 -7
  150. data/spec/integration/scoped_search_spec.rb +193 -74
  151. data/spec/integration/spellcheck_spec.rb +119 -0
  152. data/spec/integration/stats_spec.rb +88 -0
  153. data/spec/integration/stored_fields_spec.rb +1 -1
  154. data/spec/integration/test_pagination.rb +4 -4
  155. data/spec/integration/unicode_spec.rb +1 -1
  156. data/spec/mocks/adapters.rb +36 -0
  157. data/spec/mocks/connection.rb +5 -3
  158. data/spec/mocks/photo.rb +32 -1
  159. data/spec/mocks/post.rb +18 -3
  160. data/spec/spec_helper.rb +13 -8
  161. data/sunspot.gemspec +6 -4
  162. data/tasks/rdoc.rake +22 -14
  163. metadata +101 -44
  164. data/lib/sunspot/dsl/field_group.rb +0 -57
  165. data/lib/sunspot/query/field_group.rb +0 -37
@@ -114,6 +114,47 @@ module Sunspot
114
114
  "geodist(#{@field.indexed_name.to_sym},#{@lat},#{@lon}) #{direction_for_solr}"
115
115
  end
116
116
  end
117
+
118
+ class SolrIdSort < Abstract
119
+ def to_param
120
+ "id #{direction_for_solr}"
121
+ end
122
+ end
123
+
124
+ #
125
+ # A FunctionSort sorts by solr function.
126
+ # FunctionComp recursively parses arguments for nesting
127
+ #
128
+ class FunctionSort < Abstract
129
+ attr_reader :comp
130
+ def initialize(setup,args)
131
+ @direction = args.pop
132
+ @comp = FunctionComp.new(setup,args)
133
+ end
134
+ def to_param
135
+ "#{comp.to_s} #{direction_for_solr}"
136
+ end
137
+ end
138
+ class FunctionComp
139
+ attr_accessor :function,:fields
140
+ def initialize(setup,args)
141
+ @function=args.shift
142
+ @fields = []
143
+ args.each do |argument|
144
+ case argument.class.name
145
+ when "Array"
146
+ @fields<< FunctionComp.new(setup,argument)
147
+ when "Symbol"
148
+ @fields<< setup.field(argument).indexed_name
149
+ else
150
+ @fields<< argument
151
+ end
152
+ end
153
+ end
154
+ def to_s
155
+ "#{function}(#{fields.map(&:to_s).join(",")})"
156
+ end
157
+ end
117
158
  end
118
159
  end
119
160
  end
@@ -18,6 +18,13 @@ module Sunspot
18
18
  @sorts << sort
19
19
  end
20
20
 
21
+ #
22
+ # Check sort presence
23
+ #
24
+ def include?(sort)
25
+ @sorts.any? { |s| s.to_param.include?(sort) }
26
+ end
27
+
21
28
  #
22
29
  # Combine the sorts into a single param by joining them
23
30
  #
@@ -0,0 +1,19 @@
1
+ module Sunspot
2
+ module Query
3
+ class Spellcheck < Connective::Conjunction
4
+ attr_accessor :options
5
+
6
+ def initialize(options = {})
7
+ @options = options
8
+ end
9
+
10
+ def to_params
11
+ options = {}
12
+ @options.each do |key, val|
13
+ options["spellcheck." + Sunspot::Util.method_case(key.to_s)] = val
14
+ end
15
+ { :spellcheck => true }.merge(options)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -5,11 +5,33 @@ module Sunspot
5
5
 
6
6
  def initialize(types)
7
7
  super
8
- @components << @fulltext = CompositeFulltext.new
8
+ @components << @fulltext = Conjunction.new
9
9
  end
10
10
 
11
11
  def add_fulltext(keywords)
12
- @fulltext.add(keywords)
12
+ @fulltext.add_fulltext(keywords)
13
+ end
14
+
15
+ def add_join(keywords, target, from, to)
16
+ @fulltext.add_join(keywords, target, from, to)
17
+ end
18
+
19
+ def disjunction
20
+ parent_fulltext = @fulltext
21
+ @fulltext = @fulltext.add_disjunction
22
+
23
+ yield
24
+ ensure
25
+ @fulltext = parent_fulltext
26
+ end
27
+
28
+ def conjunction
29
+ parent_fulltext = @fulltext
30
+ @fulltext = @fulltext.add_conjunction
31
+
32
+ yield
33
+ ensure
34
+ @fulltext = parent_fulltext
13
35
  end
14
36
  end
15
37
  end
@@ -8,9 +8,7 @@ module Sunspot
8
8
  end
9
9
 
10
10
  def to_boosted_field
11
- boosted_field = @field.indexed_name
12
- boosted_field.concat("^#{@boost}") if @boost
13
- boosted_field
11
+ @boost ? "#{@field.indexed_name}^#{@boost}" : @field.indexed_name
14
12
  end
15
13
  end
16
14
  end
@@ -23,7 +23,8 @@ module Sunspot
23
23
  FieldType.new('slong', 'SortableLong', 'l'),
24
24
  FieldType.new('tint', 'TrieInteger', 'it'),
25
25
  FieldType.new('tfloat', 'TrieFloat', 'ft'),
26
- FieldType.new('tdate', 'TrieInt', 'dt')
26
+ FieldType.new('tdate', 'TrieInt', 'dt'),
27
+ FieldType.new('daterange', 'DateRange', 'dr')
27
28
 
28
29
  ]
29
30
 
@@ -87,8 +88,16 @@ module Sunspot
87
88
  # Return an XML representation of this schema using the ERB template
88
89
  #
89
90
  def to_xml
90
- template = File.join(File.dirname(__FILE__), '..', '..', 'templates', 'schema.xml.erb')
91
- ERB.new(File.read(template), nil, '-').result(binding)
91
+ template_path = File.join(File.dirname(__FILE__), '..', '..', 'templates', 'schema.xml.erb')
92
+ template_text = File.read(template_path)
93
+
94
+ erb = if RUBY_VERSION >= '2.6'
95
+ ERB.new(template_text, trim_mode: '-')
96
+ else
97
+ ERB.new(template_text, nil, '-')
98
+ end
99
+
100
+ erb.result(binding)
92
101
  end
93
102
 
94
103
  private
@@ -1,5 +1,7 @@
1
- %w(abstract_search standard_search more_like_this_search query_facet field_facet
2
- date_facet range_facet facet_row hit highlight field_group group hit_enumerable).each do |file|
1
+ %w(abstract_search standard_search more_like_this_search query_facet
2
+ field_facet field_json_facet date_facet range_facet json_facet_stats
3
+ facet_row json_facet_row hit highlight field_group group hit_enumerable
4
+ stats_row stats_json_row field_stats stats_facet query_group).each do |file|
3
5
  require File.join(File.dirname(__FILE__), 'search', file)
4
6
  end
5
7
 
@@ -1,17 +1,18 @@
1
1
  require 'sunspot/search/paginated_collection'
2
+ require 'sunspot/search/cursor_paginated_collection'
2
3
  require 'sunspot/search/hit_enumerable'
3
4
 
4
5
  module Sunspot
5
6
  module Search #:nodoc:
6
-
7
- #
7
+
8
+ #
8
9
  # This class encapsulates the results of a Solr search. It provides access
9
10
  # to search results, total result count, facets, and pagination information.
10
11
  # Instances of Search are returned by the Sunspot.search and
11
12
  # Sunspot.new_search methods.
12
13
  #
13
14
  class AbstractSearch
14
- #
15
+ #
15
16
  # Retrieve all facet objects defined for this search, in order they were
16
17
  # defined. To retrieve an individual facet by name, use #facet()
17
18
  #
@@ -20,7 +21,7 @@ module Sunspot
20
21
  attr_accessor :request_handler
21
22
 
22
23
  include HitEnumerable
23
-
24
+
24
25
  def initialize(connection, setup, query, configuration) #:nodoc:
25
26
  @connection, @setup, @query = connection, setup, query
26
27
  @query.paginate(1, configuration.pagination.default_per_page)
@@ -30,8 +31,11 @@ module Sunspot
30
31
 
31
32
  @groups_by_name = {}
32
33
  @groups = []
34
+
35
+ @stats_by_name = {}
36
+ @stats = []
33
37
  end
34
-
38
+
35
39
  #
36
40
  # Execute the search on the Solr instance and store the results. If you
37
41
  # use Sunspot#search() to construct your searches, there is no need to call
@@ -49,8 +53,8 @@ module Sunspot
49
53
  def execute! #:nodoc: deprecated
50
54
  execute
51
55
  end
52
-
53
- #
56
+
57
+ #
54
58
  # Get the collection of results as instantiated objects. If WillPaginate is
55
59
  # available, the results will be a WillPaginate::Collection instance; if
56
60
  # not, it will be a vanilla Array.
@@ -65,8 +69,8 @@ module Sunspot
65
69
  def results
66
70
  @results ||= paginate_collection(verified_hits.map { |hit| hit.instance })
67
71
  end
68
-
69
- #
72
+
73
+ #
70
74
  # Access raw Solr result information. Returns a collection of Hit objects
71
75
  # that contain the class name, primary key, keyword relevance score (if
72
76
  # applicable), and any stored fields.
@@ -92,7 +96,7 @@ module Sunspot
92
96
  end
93
97
  alias_method :raw_results, :hits
94
98
 
95
- #
99
+ #
96
100
  # The total number of documents matching the query parameters
97
101
  #
98
102
  # ==== Returns
@@ -102,8 +106,8 @@ module Sunspot
102
106
  def total
103
107
  @total ||= solr_response['numFound'] || 0
104
108
  end
105
-
106
- #
109
+
110
+ #
107
111
  # The time elapsed to generate the Solr response
108
112
  #
109
113
  # ==== Returns
@@ -113,8 +117,8 @@ module Sunspot
113
117
  def query_time
114
118
  @query_time ||= solr_response_header['QTime']
115
119
  end
116
-
117
- #
120
+
121
+ #
118
122
  # Get the facet object for the given name. `name` can either be the name
119
123
  # given to a query facet, or the field name of a field facet. Returns a
120
124
  # Sunspot::Facet object.
@@ -156,11 +160,19 @@ module Sunspot
156
160
  #
157
161
  def facet(name, dynamic_name = nil)
158
162
  if name
159
- if dynamic_name
160
- @facets_by_name[:"#{name}:#{dynamic_name}"]
161
- else
162
- @facets_by_name[name.to_sym]
163
- end
163
+ facet_name = if dynamic_name
164
+ separator = @setup.dynamic_field_factory(name).separator
165
+ [name, dynamic_name].join(separator)
166
+ else
167
+ name
168
+ end.to_sym
169
+ @facets_by_name[facet_name]
170
+ end
171
+ end
172
+
173
+ def stats(name)
174
+ if name
175
+ @stats_by_name[name.to_sym]
164
176
  end
165
177
  end
166
178
 
@@ -169,23 +181,35 @@ module Sunspot
169
181
  @groups_by_name[name.to_sym]
170
182
  end
171
183
  end
172
-
173
- #
184
+
185
+ def json_facet_stats(name, options = {})
186
+ JsonFacetStats.new(name, self, options)
187
+ end
188
+
189
+ #
174
190
  # Deprecated in favor of optional second argument to #facet
175
191
  #
176
192
  def dynamic_facet(base_name, dynamic_name) #:nodoc:
177
193
  facet(base_name, dynamic_name)
178
194
  end
179
-
195
+
180
196
  def facet_response #:nodoc:
181
197
  @solr_result['facet_counts']
182
198
  end
183
199
 
200
+ def json_facet_response #:nodoc:
201
+ @solr_result['facets']
202
+ end
203
+
204
+ def stats_response #:nodoc:
205
+ @solr_result['stats']['stats_fields']
206
+ end
207
+
184
208
  def group_response #:nodoc:
185
209
  @solr_result['grouped']
186
210
  end
187
-
188
- #
211
+
212
+ #
189
213
  # Build this search using a DSL block. This method can be called more than
190
214
  # once on an unexecuted search (e.g., Sunspot.new_search) in order to build
191
215
  # a search incrementally.
@@ -202,25 +226,29 @@ module Sunspot
202
226
  Util.instance_eval_or_call(dsl, &block)
203
227
  self
204
228
  end
205
-
206
-
229
+
230
+
207
231
  def inspect #:nodoc:
208
232
  "<Sunspot::Search:#{query.to_params.inspect}>"
209
233
  end
210
234
 
211
- def add_field_group(field) #:nodoc:
212
- add_group(field.name, FieldGroup.new(field, self))
235
+ def add_group(group) #:nodoc:
236
+ group.fields.each do |field|
237
+ add_subgroup(field.name, FieldGroup.new(field, self))
238
+ end
239
+
240
+ add_subgroup(:queries, QueryGroup.new(group.queries, self)) if group.queries.any?
213
241
  end
214
-
242
+
215
243
  def add_field_facet(field, options = {}) #:nodoc:
216
244
  name = (options[:name] || field.name)
217
245
  add_facet(name, FieldFacet.new(field, self, options))
218
246
  end
219
-
247
+
220
248
  def add_query_facet(name, options) #:nodoc:
221
249
  add_facet(name, QueryFacet.new(name, self, options))
222
250
  end
223
-
251
+
224
252
  def add_date_facet(field, options) #:nodoc:
225
253
  name = (options[:name] || field.name)
226
254
  add_facet(name, DateFacet.new(field, self, options))
@@ -231,26 +259,35 @@ module Sunspot
231
259
  add_facet(name, RangeFacet.new(field, self, options))
232
260
  end
233
261
 
262
+ def add_field_stats(field) #:nodoc:
263
+ add_stats(field.name, FieldStats.new(field, self))
264
+ end
265
+
266
+ def add_json_facet(field, options = {})
267
+ name = (options[:name] || field.name)
268
+ add_facet(name, FieldJsonFacet.new(field, self, options))
269
+ end
270
+
234
271
  def highlights_for(doc) #:nodoc:
235
272
  if @solr_result['highlighting']
236
273
  @solr_result['highlighting'][doc['id']]
237
274
  end
238
275
  end
239
-
276
+
240
277
  private
241
-
278
+
242
279
  def dsl
243
- raise NotImplementedError
280
+ raise NotImplementedError
244
281
  end
245
-
282
+
246
283
  def execute_request(params)
247
284
  raise NotImplementedError
248
285
  end
249
-
286
+
250
287
  def solr_response
251
288
  @solr_response ||= @solr_result['response'] || {}
252
289
  end
253
-
290
+
254
291
  def solr_response_header
255
292
  @solr_response_header ||= @solr_result['responseHeader'] || {}
256
293
  end
@@ -258,25 +295,38 @@ module Sunspot
258
295
  def solr_docs
259
296
  solr_response['docs']
260
297
  end
261
-
298
+
299
+ def next_cursor
300
+ @solr_result['nextCursorMark'] if @query.cursor
301
+ end
302
+
262
303
  def verified_hits
263
304
  @verified_hits ||= paginate_collection(super)
264
305
  end
265
-
306
+
266
307
  def paginate_collection(collection)
267
- PaginatedCollection.new(collection, @query.page, @query.per_page, total)
308
+ if @query.cursor
309
+ CursorPaginatedCollection.new(collection, @query.per_page, total, @query.cursor, next_cursor)
310
+ else
311
+ PaginatedCollection.new(collection, @query.page, @query.per_page, total)
312
+ end
268
313
  end
269
-
314
+
270
315
  def add_facet(name, facet)
271
316
  @facets << facet
272
317
  @facets_by_name[name.to_sym] = facet
273
318
  end
274
319
 
275
- def add_group(name, group)
320
+ def add_stats(name, stats)
321
+ @stats << stats
322
+ @stats_by_name[name.to_sym] = stats
323
+ end
324
+
325
+ def add_subgroup(name, group)
276
326
  @groups << group
277
327
  @groups_by_name[name.to_sym] = group
278
328
  end
279
-
329
+
280
330
  # Clear out all the cached ivars so the search can be called again.
281
331
  def reset
282
332
  @results = @hits = @verified_hits = @total = @solr_response = @doc_ids = nil