sunspot 2.0.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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