sunspot 2.5.0 → 2.7.1

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sunspot/adapters.rb +14 -3
  3. data/lib/sunspot/data_extractor.rb +1 -1
  4. data/lib/sunspot/dsl/fulltext.rb +1 -1
  5. data/lib/sunspot/dsl/standard_query.rb +29 -1
  6. data/lib/sunspot/dsl.rb +2 -2
  7. data/lib/sunspot/field.rb +21 -4
  8. data/lib/sunspot/indexer.rb +37 -8
  9. data/lib/sunspot/query/abstract_fulltext.rb +7 -3
  10. data/lib/sunspot/query/abstract_json_field_facet.rb +3 -0
  11. data/lib/sunspot/query/composite_fulltext.rb +21 -2
  12. data/lib/sunspot/query/date_field_json_facet.rb +2 -16
  13. data/lib/sunspot/query/dismax.rb +10 -4
  14. data/lib/sunspot/query/function_query.rb +25 -1
  15. data/lib/sunspot/query/join.rb +1 -1
  16. data/lib/sunspot/query/range_json_facet.rb +5 -2
  17. data/lib/sunspot/query/restriction.rb +16 -10
  18. data/lib/sunspot/query/standard_query.rb +12 -0
  19. data/lib/sunspot/search/field_json_facet.rb +14 -3
  20. data/lib/sunspot/session.rb +7 -5
  21. data/lib/sunspot/setup.rb +38 -0
  22. data/lib/sunspot/util.rb +24 -21
  23. data/lib/sunspot/version.rb +1 -1
  24. data/lib/sunspot.rb +9 -1
  25. data/spec/api/binding_spec.rb +15 -0
  26. data/spec/api/indexer/attributes_spec.rb +1 -1
  27. data/spec/api/indexer/removal_spec.rb +87 -0
  28. data/spec/api/query/connective_boost_examples.rb +85 -0
  29. data/spec/api/query/geo_examples.rb +1 -1
  30. data/spec/api/query/join_spec.rb +2 -2
  31. data/spec/api/query/standard_spec.rb +10 -0
  32. data/spec/api/query/types_spec.rb +2 -2
  33. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +1 -1
  34. data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +9 -5
  35. data/spec/api/session_spec.rb +1 -1
  36. data/spec/api/setup_spec.rb +99 -0
  37. data/spec/helpers/indexer_helper.rb +22 -0
  38. data/spec/integration/atomic_updates_spec.rb +169 -5
  39. data/spec/integration/faceting_spec.rb +68 -34
  40. data/spec/integration/join_spec.rb +22 -3
  41. data/spec/integration/scoped_search_spec.rb +78 -0
  42. data/spec/mocks/comment.rb +1 -1
  43. data/spec/mocks/connection.rb +6 -0
  44. data/spec/mocks/photo.rb +11 -7
  45. data/spec/mocks/post.rb +35 -1
  46. data/sunspot.gemspec +4 -6
  47. metadata +33 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 179de5f5261bdb69d21038a0b2e36fbd2812e1fc71ef4c1efd77979a03e58179
4
- data.tar.gz: 1f7f40d9737400cf61c23515c61ebde70140b1c1bf9df800d7e19ce27c3cbd0d
3
+ metadata.gz: f9749564050cadeb45de77d96ed183f7bb07a856b5199fea3bbede0365147e97
4
+ data.tar.gz: 5bdedfb6911ecbad36de8314822b536c6fb698e6432dcea03bd23be14672dcf7
5
5
  SHA512:
6
- metadata.gz: ad59d5868f3461648d29c77b6368d7c5145ef6247ecca38878bf4f03bb3d2ab73fea2decf629936d58282b8067345198f6bff82be1347bb0cc92cb4537722d28
7
- data.tar.gz: 3c4fd67940331fbdacffd665ca624119038bf12da2aa2b041adbd8260aef3921660b83803a912cf81384c7269f6b46d3b7fad1c883c34e1a1ba2ccbade2fd6dc
6
+ metadata.gz: 1850a3b888c9589cb98878344d76d95882ebd95f8aae56095767a0ed3b49787a1c65cb5f1c3c84406afcc2c8cf8da4d533434b9e2850c3bd635a4417d45c14e4
7
+ data.tar.gz: 5d1a20b95d6f11caab821b186952d05e3c68a86b7e23bf673f451b23fa0429df0f4113e2a91cd12c50617375456b00d41656c7b5c7d402450b08e5df22b69b89
@@ -55,6 +55,20 @@ module Sunspot
55
55
  @instance = instance
56
56
  end
57
57
 
58
+ #
59
+ # An ID prefix to be added to the index_id
60
+ #
61
+ # ==== Returns
62
+ #
63
+ # String:: ID prefix for use in index ID to determine
64
+ # the shard a document is sent to for indexing
65
+ #
66
+ def id_prefix
67
+ setup = Sunspot::Setup.for(@instance.class)
68
+
69
+ setup && setup.id_prefix_for(@instance)
70
+ end
71
+
58
72
  #
59
73
  # The universally-unique ID for this instance that will be stored in solr
60
74
  #
@@ -63,9 +77,6 @@ module Sunspot
63
77
  # String:: ID for use in Solr
64
78
  #
65
79
  def index_id #:nodoc:
66
- setup = Sunspot::Setup.for(@instance.class)
67
- id_prefix = setup ? setup.id_prefix_for(@instance) : nil
68
-
69
80
  InstanceAdapter.index_id_for("#{id_prefix}#{@instance.class.name}", id)
70
81
  end
71
82
 
@@ -9,7 +9,7 @@ module Sunspot
9
9
  # Abstract extractor to perform common actions on extracted values
10
10
  #
11
11
  class AbstractExtractor
12
- BLACKLIST_REGEXP = /[\x0-\x8\xB\xC\xE-\x1F\x7f]/
12
+ BLACKLIST_REGEXP = /[\x0-\x8\xB\xC\xE-\x1F\x7f\uFFFE-\uFFFF]/
13
13
 
14
14
  def value_for(object)
15
15
  extract_value_from(object)
@@ -176,7 +176,7 @@ module Sunspot
176
176
  @query.add_additive_boost_function(factor_or_function)
177
177
  else
178
178
  Sunspot::Util.instance_eval_or_call(
179
- Scope.new(@query.create_boost_query(factor_or_function), @setup),
179
+ Scope.new(@query.add_boost_query(factor_or_function), @setup),
180
180
  &block
181
181
  )
182
182
  end
@@ -9,7 +9,7 @@ module Sunspot
9
9
  # See Sunspot.search for usage examples
10
10
  #
11
11
  class StandardQuery < FieldQuery
12
- include Paginatable, Adjustable, Spellcheckable
12
+ include Paginatable, Adjustable, Spellcheckable, Functional
13
13
 
14
14
  # Specify a phrase that should be searched as fulltext. Only +text+
15
15
  # fields are searched - see DSL::Fields.text
@@ -123,6 +123,34 @@ module Sunspot
123
123
  end
124
124
  end
125
125
 
126
+ #
127
+ # Defines a boost query
128
+ #
129
+ # === Examples
130
+ #
131
+ # Sunspot.search(Post) do
132
+ # with(:blog_id, 1)
133
+ #
134
+ # boost(10) do
135
+ # with(:category_id, 2)
136
+ # end
137
+ # end
138
+ #
139
+ def boost(factor_or_function, &block)
140
+ if factor_or_function.is_a?(Sunspot::Query::FunctionQuery)
141
+ @query.add_boost_function(factor_or_function)
142
+ else
143
+ Sunspot::Util.instance_eval_or_call(
144
+ Scope.new(@query.add_boost_query(factor_or_function), @setup),
145
+ &block
146
+ )
147
+ end
148
+ end
149
+
150
+ def boost_multiplicative(factor_or_function)
151
+ @query.add_multiplicative_boost_function(factor_or_function)
152
+ end
153
+
126
154
  private
127
155
 
128
156
  def add_fulltext(keywords, field_names)
data/lib/sunspot/dsl.rb CHANGED
@@ -1,5 +1,5 @@
1
- %w(spellcheckable fields scope paginatable adjustable field_query
2
- standard_query query_facet functional fulltext restriction
1
+ %w(spellcheckable fields functional scope paginatable adjustable field_query
2
+ standard_query query_facet fulltext restriction
3
3
  restriction_with_near search more_like_this_query function
4
4
  group field_stats).each do |file|
5
5
  require File.join(File.dirname(__FILE__), 'dsl', file)
data/lib/sunspot/field.rb CHANGED
@@ -195,7 +195,7 @@ module Sunspot
195
195
  # Could be of any type
196
196
  #
197
197
  class JoinField < Field #:nodoc:
198
- attr_reader :default_boost, :target
198
+ attr_reader :default_boost
199
199
 
200
200
  def initialize(name, type, options = {})
201
201
  @multiple = !!options.delete(:multiple)
@@ -213,15 +213,21 @@ module Sunspot
213
213
  end
214
214
 
215
215
  def from
216
- Sunspot::Setup.for(@target).field(@join[:from]).indexed_name
216
+ Sunspot::Setup.for(target).field(@join[:from]).indexed_name
217
217
  end
218
218
 
219
219
  def to
220
220
  Sunspot::Setup.for(@clazz).field(@join[:to]).indexed_name
221
221
  end
222
222
 
223
- def local_params
224
- "{!join from=#{from} to=#{to}}"
223
+ def local_params(value)
224
+ query = ["type:\"#{target.name}\""] | Util.Array(value)
225
+
226
+ "{!join from=#{from} to=#{to} v='#{query.join(' AND ')}'}"
227
+ end
228
+
229
+ def to_solr_conditional(value)
230
+ "\"#{value}\""
225
231
  end
226
232
 
227
233
  def eql?(field)
@@ -229,9 +235,16 @@ module Sunspot
229
235
  end
230
236
 
231
237
  alias_method :==, :eql?
238
+
239
+ def target
240
+ @target = Util.full_const_get(@target) if @target.is_a?(String)
241
+ @target
242
+ end
232
243
  end
233
244
 
234
245
  class TypeField #:nodoc:
246
+ MODULAR_MODEL_MARK = '\:\:'
247
+
235
248
  class <<self
236
249
  def instance
237
250
  @instance ||= new
@@ -245,6 +258,10 @@ module Sunspot
245
258
  def to_indexed(clazz)
246
259
  clazz.name
247
260
  end
261
+
262
+ def to_solr_conditional(value)
263
+ value.include?(MODULAR_MODEL_MARK) ? "\"#{value}\"" : value
264
+ end
248
265
  end
249
266
 
250
267
  class IdField #:nodoc:
@@ -54,9 +54,24 @@ module Sunspot
54
54
  # Remove the model from the Solr index by specifying the class and ID
55
55
  #
56
56
  def remove_by_id(class_name, *ids)
57
+ if class_name.is_a?(String) and class_name.index("!")
58
+ partition = class_name.rpartition("!")
59
+ id_prefix = partition[0..1].join
60
+ class_name = partition[2]
61
+ else
62
+ clazz_setup = setup_for_class(Util.full_const_get(class_name))
63
+ id_prefix = if clazz_setup.id_prefix_defined?
64
+ if clazz_setup.id_prefix_requires_instance?
65
+ warn(Sunspot::RemoveByIdNotSupportCompositeIdMessage.call(class_name))
66
+ else
67
+ clazz_setup.id_prefix_for_class
68
+ end
69
+ end
70
+ end
71
+
57
72
  ids.flatten!
58
73
  @connection.delete_by_id(
59
- ids.map { |id| Adapters::InstanceAdapter.index_id_for(class_name, id) }
74
+ ids.map { |id| Adapters::InstanceAdapter.index_id_for("#{id_prefix}#{class_name}", id) }
60
75
  )
61
76
  end
62
77
 
@@ -147,13 +162,27 @@ module Sunspot
147
162
  )
148
163
  end
149
164
 
150
- def document_for_atomic_update(clazz, id)
151
- if Adapters::InstanceAdapter.for(clazz)
152
- RSolr::Xml::Document.new(
153
- id: Adapters::InstanceAdapter.index_id_for(clazz.name, id),
154
- type: Util.superclasses_for(clazz).map(&:name)
155
- )
156
- end
165
+ def document_for_atomic_update(clazz, key)
166
+ return unless Adapters::InstanceAdapter.for(clazz)
167
+
168
+ clazz_setup = setup_for_class(clazz)
169
+ id_prefix = if clazz_setup.id_prefix_defined?
170
+ if clazz_setup.id_prefix_requires_instance?
171
+ if key.respond_to?(:id)
172
+ clazz_setup.id_prefix_for(key)
173
+ else
174
+ warn(Sunspot::AtomicUpdateRequireInstanceForCompositeIdMessage.call(clazz.name))
175
+ end
176
+ else
177
+ clazz_setup.id_prefix_for_class
178
+ end
179
+ end
180
+
181
+ instance_id = key.respond_to?(:id) ? key.id : key
182
+ RSolr::Xml::Document.new(
183
+ id: Adapters::InstanceAdapter.index_id_for("#{id_prefix}#{clazz.name}", instance_id),
184
+ type: Util.superclasses_for(clazz).map(&:name)
185
+ )
157
186
  end
158
187
  #
159
188
  # Get the Setup object for the given object's class.
@@ -10,7 +10,7 @@ module Sunspot
10
10
  #
11
11
  # Assign a new boost query and return it.
12
12
  #
13
- def create_boost_query(factor)
13
+ def add_boost_query(factor)
14
14
  @boost_queries << boost_query = BoostQuery.new(factor)
15
15
  boost_query
16
16
  end
@@ -19,14 +19,18 @@ module Sunspot
19
19
  # Add a boost function
20
20
  #
21
21
  def add_additive_boost_function(function_query)
22
- @additive_boost_functions << function_query
22
+ unless @additive_boost_functions.include?(function_query)
23
+ @additive_boost_functions << function_query
24
+ end
23
25
  end
24
26
 
25
27
  #
26
28
  # Add a multiplicative boost function
27
29
  #
28
30
  def add_multiplicative_boost_function(function_query)
29
- @multiplicative_boost_functions << function_query
31
+ unless @multiplicative_boost_functions.include?(function_query)
32
+ @multiplicative_boost_functions << function_query
33
+ end
30
34
  end
31
35
 
32
36
  #
@@ -17,6 +17,9 @@ module Sunspot
17
17
  params[:sort] = { @options[:sort] => @options[:sort_type]||'desc' } unless @options[:sort].nil?
18
18
  params[:prefix] = @options[:prefix] unless @options[:prefix].nil?
19
19
  params[:offset] = @options[:offset] unless @options[:offset].nil?
20
+ params[:allBuckets] = @options[:all_buckets] unless @options[:all_buckets].nil?
21
+ params[:missing] = @options[:missing] unless @options[:missing].nil?
22
+ params[:method] = @options[:method] unless @options[:method].nil?
20
23
 
21
24
  if !@options[:distinct].nil?
22
25
  dist_opts = @options[:distinct]
@@ -3,11 +3,30 @@ module Sunspot
3
3
  class CompositeFulltext
4
4
  def initialize
5
5
  @components = []
6
+ @dismax = nil
6
7
  end
7
8
 
8
9
  def add_fulltext(keywords)
9
- @components << dismax = Dismax.new(keywords)
10
- dismax
10
+ @components << @dismax = Dismax.new(keywords)
11
+ @dismax
12
+ end
13
+
14
+ def add_boost_query(factor)
15
+ @dismax ||= Dismax.new("*:*")
16
+ @components << @dismax unless @components.include?(@dismax)
17
+ @dismax.add_boost_query(factor)
18
+ end
19
+
20
+ def add_boost_function(function)
21
+ @dismax ||= Dismax.new("*:*")
22
+ @components << @dismax unless @components.include?(@dismax)
23
+ @dismax.add_additive_boost_function(function)
24
+ end
25
+
26
+ def add_multiplicative_boost_function(function)
27
+ @dismax ||= Dismax.new("*:*")
28
+ @components << @dismax unless @components.include?(@dismax)
29
+ @dismax.add_multiplicative_boost_function(function)
11
30
  end
12
31
 
13
32
  def add_join(keywords, target, from, to)
@@ -1,24 +1,10 @@
1
1
  module Sunspot
2
2
  module Query
3
- class DateFieldJsonFacet < AbstractJsonFieldFacet
3
+ class DateFieldJsonFacet < RangeJsonFacet
4
4
 
5
5
  def initialize(field, options, setup)
6
- raise Exception.new('Need to specify a time_range') if options[:time_range].nil?
7
- @start = options[:time_range].first
8
- @end = options[:time_range].last
9
- @gap = "+#{options[:gap] || 86400}SECONDS"
10
6
  super
11
- end
12
-
13
- def field_name_with_local_params
14
- params = {}
15
- params[:type] = 'range'
16
- params[:field] = @field.indexed_name
17
- params[:start] = @field.to_indexed(@start)
18
- params[:end] = @field.to_indexed(@end)
19
- params[:gap] = @gap
20
- params.merge!(init_params)
21
- { @field.name => params }
7
+ @gap = "+#{@gap}#{options[:gap_unit] || 'SECONDS'}"
22
8
  end
23
9
  end
24
10
  end
@@ -28,10 +28,16 @@ module Sunspot
28
28
  # The query as Solr parameters
29
29
  #
30
30
  def to_params
31
- params = { :q => @keywords }
32
- params[:fl] = '* score'
33
- params[:qf] = @fulltext_fields.values.map { |field| field.to_boosted_field }.join(' ')
34
- params[:defType] = 'edismax'
31
+ params = {
32
+ :q => @keywords,
33
+ :defType => 'edismax',
34
+ :fl => '* score'
35
+ }
36
+
37
+ if @fulltext_fields.any?
38
+ params[:qf] = @fulltext_fields.values.map { |field| field.to_boosted_field }.join(' ')
39
+ end
40
+
35
41
  params[:mm] = @minimum_match if @minimum_match
36
42
  params[:ps] = @phrase_slop if @phrase_slop
37
43
  params[:qs] = @query_phrase_slop if @query_phrase_slop
@@ -3,18 +3,25 @@ module Sunspot
3
3
  #
4
4
  # Abstract class for function queries.
5
5
  #
6
- class FunctionQuery
6
+ class FunctionQuery
7
+ attr_reader :boost_amount
7
8
 
8
9
  def ^(y)
9
10
  @boost_amount = y
10
11
  self
11
12
  end
13
+
14
+ def ==(other)
15
+ @boost_amount == other.boost_amount
16
+ end
12
17
  end
13
18
 
14
19
  #
15
20
  # Function query which represents a constant.
16
21
  #
17
22
  class ConstantFunctionQuery < FunctionQuery
23
+ attr_reader :constant
24
+
18
25
  def initialize(constant)
19
26
  @constant = constant
20
27
  end
@@ -22,12 +29,18 @@ module Sunspot
22
29
  def to_s
23
30
  Type.to_literal(@constant) << (@boost_amount ? "^#{@boost_amount}" : "")
24
31
  end
32
+
33
+ def ==(other)
34
+ super and @constant == other.constant
35
+ end
25
36
  end
26
37
 
27
38
  #
28
39
  # Function query which represents a field.
29
40
  #
30
41
  class FieldFunctionQuery < FunctionQuery
42
+ attr_reader :field
43
+
31
44
  def initialize(field)
32
45
  @field = field
33
46
  end
@@ -35,6 +48,10 @@ module Sunspot
35
48
  def to_s
36
49
  "#{Util.escape(@field.indexed_name)}" << (@boost_amount ? "^#{@boost_amount}" : "")
37
50
  end
51
+
52
+ def ==(other)
53
+ super and @field == other.field
54
+ end
38
55
  end
39
56
 
40
57
  #
@@ -43,6 +60,8 @@ module Sunspot
43
60
  # Arguments are in turn FunctionQuery objects.
44
61
  #
45
62
  class FunctionalFunctionQuery < FunctionQuery
63
+ attr_reader :function_name, :function_args
64
+
46
65
  def initialize(function_name, function_args)
47
66
  @function_name, @function_args = function_name, function_args
48
67
  end
@@ -51,6 +70,11 @@ module Sunspot
51
70
  params = @function_args.map { |arg| arg.to_s }.join(",")
52
71
  "#{@function_name}(#{params})" << (@boost_amount ? "^#{@boost_amount}" : "")
53
72
  end
73
+
74
+ def ==(other)
75
+ super and
76
+ @function_name == other.function_name and @function_args == other.function_args
77
+ end
54
78
  end
55
79
  end
56
80
  end
@@ -52,7 +52,7 @@ module Sunspot
52
52
  #
53
53
  # Assign a new boost query and return it.
54
54
  #
55
- def create_boost_query(factor)
55
+ def add_boost_query(factor)
56
56
  end
57
57
 
58
58
  #
@@ -5,10 +5,12 @@ module Sunspot
5
5
  SECONDS_IN_DAY = 86400
6
6
 
7
7
  def initialize(field, options, setup)
8
- raise Exception.new("Need to specify a range") if options[:range].nil?
8
+ options[:range] ||= options[:time_range]
9
+ raise Exception.new("Need to specify a range") if options[:range].nil? && options[:time_range].nil?
9
10
  @start = options[:range].first
10
11
  @end = options[:range].last
11
12
  @gap = options[:gap] || SECONDS_IN_DAY
13
+ @other = options[:other]
12
14
  super
13
15
  end
14
16
 
@@ -19,7 +21,8 @@ module Sunspot
19
21
  field: @field.indexed_name,
20
22
  start: @field.to_indexed(@start),
21
23
  end: @field.to_indexed(@end),
22
- gap: @gap
24
+ gap: @gap,
25
+ other: @other
23
26
  }.merge!(init_params)
24
27
  }
25
28
  end
@@ -78,14 +78,14 @@ module Sunspot
78
78
  # on whether this restriction is negated.
79
79
  #
80
80
  def to_boolean_phrase
81
- phrase = []
82
- phrase << @field.local_params if @field.respond_to? :local_params
83
- unless negated?
84
- phrase << to_positive_boolean_phrase
85
- else
86
- phrase << to_negated_boolean_phrase
87
- end
88
- phrase.join
81
+ value = if negated?
82
+ to_negated_boolean_phrase
83
+ else
84
+ to_positive_boolean_phrase
85
+ end
86
+
87
+ @field.respond_to?(:local_params) ?
88
+ @field.local_params(value) : value
89
89
  end
90
90
 
91
91
  #
@@ -208,7 +208,8 @@ module Sunspot
208
208
  private
209
209
 
210
210
  def to_solr_conditional
211
- "#{solr_value}"
211
+ @field.respond_to?(:to_solr_conditional) ?
212
+ @field.to_solr_conditional(solr_value) : "#{solr_value}"
212
213
  end
213
214
  end
214
215
 
@@ -316,9 +317,14 @@ module Sunspot
316
317
  if @value.empty?
317
318
  "[* TO *]"
318
319
  else
319
- "(#{@value.map { |v| solr_value v } * ' OR '})"
320
+ "(#{@value.map { |v| to_solr_conditional_per_value v } * ' OR '})"
320
321
  end
321
322
  end
323
+
324
+ def to_solr_conditional_per_value(v)
325
+ @field.respond_to?(:to_solr_conditional) ?
326
+ @field.to_solr_conditional(solr_value(v)) : "#{solr_value(v)}"
327
+ end
322
328
  end
323
329
 
324
330
  #
@@ -16,6 +16,18 @@ module Sunspot
16
16
  @fulltext.add_join(keywords, target, from, to)
17
17
  end
18
18
 
19
+ def add_boost_query(factor)
20
+ @fulltext.add_boost_query(factor)
21
+ end
22
+
23
+ def add_boost_function(function)
24
+ @fulltext.add_boost_function(function)
25
+ end
26
+
27
+ def add_multiplicative_boost_function(function)
28
+ @fulltext.add_multiplicative_boost_function(function)
29
+ end
30
+
19
31
  def disjunction
20
32
  parent_fulltext = @fulltext
21
33
  @fulltext = @fulltext.add_disjunction
@@ -5,15 +5,14 @@ module Sunspot
5
5
  attr_reader :name
6
6
 
7
7
  def initialize(field, search, options)
8
- @name, @search, @options = name, search, options
8
+ @name, @search, @options = (options[:name] || field.name), search, options
9
9
  @field = field
10
10
  end
11
11
 
12
12
  def rows
13
13
  @rows ||=
14
14
  begin
15
- json_facet_response = @search.json_facet_response[@field.name.to_s]
16
- data = json_facet_response.nil? ? [] : json_facet_response['buckets']
15
+ data = no_data? ? [] : @search.json_facet_response[@field.name.to_s]['buckets']
17
16
  rows = []
18
17
  data.each do |d|
19
18
  rows << JsonFacetRow.new(d, self)
@@ -28,6 +27,18 @@ module Sunspot
28
27
  end
29
28
 
30
29
  end
30
+
31
+ def no_data?
32
+ @search.json_facet_response[@field.name.to_s].nil?
33
+ end
34
+
35
+ def other_count(type)
36
+ json_facet_for_field = @search.json_facet_response[@field.name.to_s]
37
+ return 0 if json_facet_for_field.nil?
38
+
39
+ other = json_facet_for_field[type.to_s] || {}
40
+ other['count']
41
+ end
31
42
  end
32
43
  end
33
44
  end
@@ -256,10 +256,10 @@ module Sunspot
256
256
  def connection
257
257
  @connection ||= self.class.connection_class.connect(
258
258
  url: config.solr.url,
259
- read_timeout: config.solr.read_timeout,
259
+ timeout: config.solr.read_timeout,
260
260
  open_timeout: config.solr.open_timeout,
261
261
  proxy: config.solr.proxy,
262
- update_format: update_format_generator
262
+ update_format: update_format
263
263
  )
264
264
  end
265
265
 
@@ -278,9 +278,11 @@ module Sunspot
278
278
  end
279
279
  end
280
280
 
281
- def update_format_generator
282
- if config.solr.update_format && RSolr.version.to_i > 1
283
- config.solr.update_format.downcase.to_sym == :json ? RSolr::JSON::Generator : RSolr::Xml::Generator
281
+ def update_format
282
+ if config.solr.update_format && config.solr.update_format.to_s.match(/xml|json/i)
283
+ config.solr.update_format.downcase.to_sym
284
+ else
285
+ :xml
284
286
  end
285
287
  end
286
288
  end
data/lib/sunspot/setup.rb CHANGED
@@ -302,6 +302,44 @@ module Sunspot
302
302
  end
303
303
  end
304
304
 
305
+ #
306
+ # Get value for `id_prefix` defined as String
307
+ #
308
+ # ==== Returns
309
+ #
310
+ # String:: value for `id_prefix` defined as String
311
+ #
312
+ def id_prefix_for_class
313
+ return if !id_prefix_defined? || id_prefix_requires_instance?
314
+
315
+ @id_prefix_extractor.value_for(nil)
316
+ end
317
+
318
+ #
319
+ # Check if `id_prefix` is defined for class associated with this setup.
320
+ #
321
+ # ==== Returns
322
+ #
323
+ # Boolean:: True if class associated with this setup has defined `id_prefix`
324
+ #
325
+ def id_prefix_defined?
326
+ !@id_prefix_extractor.nil?
327
+ end
328
+
329
+ #
330
+ # Check if instance is required to get `id_prefix` value (instance is required for Proc and
331
+ # Symbol `id_prefix` only. Value for String `id_prefix` can be get on class level)
332
+ #
333
+ # ==== Returns
334
+ #
335
+ # Boolean:: True if instance is required to get `id_prefix` value
336
+ #
337
+ def id_prefix_requires_instance?
338
+ return false unless id_prefix_defined?
339
+
340
+ !@id_prefix_extractor.is_a?(DataExtractor::Constant)
341
+ end
342
+
305
343
  protected
306
344
 
307
345
  #