sunspot 2.0.0.pre.111215 → 2.0.0.pre.120415
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/lib/sunspot/batcher.rb +62 -0
- data/lib/sunspot/configuration.rb +2 -0
- data/lib/sunspot/dsl/field_group.rb +20 -0
- data/lib/sunspot/dsl/field_query.rb +24 -0
- data/lib/sunspot/dsl/restriction_with_near.rb +24 -2
- data/lib/sunspot/indexer.rb +11 -6
- data/lib/sunspot/query.rb +3 -3
- data/lib/sunspot/query/abstract_field_facet.rb +3 -0
- data/lib/sunspot/query/bbox.rb +15 -0
- data/lib/sunspot/query/field_group.rb +5 -3
- data/lib/sunspot/query/geofilt.rb +4 -3
- data/lib/sunspot/query/range_facet.rb +14 -0
- data/lib/sunspot/search.rb +1 -1
- data/lib/sunspot/search/abstract_search.rb +5 -0
- data/lib/sunspot/search/field_group.rb +6 -0
- data/lib/sunspot/search/group.rb +19 -0
- data/lib/sunspot/search/range_facet.rb +37 -0
- data/lib/sunspot/session.rb +3 -1
- data/lib/sunspot/session_proxy.rb +8 -0
- data/lib/sunspot/session_proxy/retry_5xx_session_proxy.rb +67 -0
- data/lib/sunspot/version.rb +1 -1
- data/spec/api/batcher_spec.rb +112 -0
- data/spec/api/indexer/batch_spec.rb +29 -3
- data/spec/api/query/faceting_examples.rb +59 -0
- data/spec/api/query/spatial_examples.rb +16 -0
- data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +73 -0
- data/spec/api/session_spec.rb +12 -0
- data/spec/integration/faceting_spec.rb +20 -0
- data/spec/integration/field_grouping_spec.rb +9 -0
- data/spec/integration/geospatial_spec.rb +27 -1
- data/spec/integration/indexing_spec.rb +22 -0
- data/sunspot.gemspec +1 -2
- metadata +35 -29
data/History.txt
CHANGED
@@ -5,6 +5,13 @@
|
|
5
5
|
* Adds #query_time method to retrieve the Solr query time in
|
6
6
|
milliseconds (Jason Weathered)
|
7
7
|
* Fixes syntax of highlighting when used with nested dismax queries (Marco Crepaldi)
|
8
|
+
* Adds ability to nest `Sunspot.batch` calls (Thorbjørn Hermansen)
|
9
|
+
* Adds `open_timeout` and `read_timeout` configuration options (Rob Di
|
10
|
+
Marco)
|
11
|
+
* Adds `offset` options to facets (Federico Gonzalez)
|
12
|
+
* Adds `Retry5xxSessionProxy` to retry requests when an internal server error
|
13
|
+
occurs (Nick Zadrozny)
|
14
|
+
* Adds support for range queries (Jan Ulrich)
|
8
15
|
|
9
16
|
== 1.3.0 2011-11-26
|
10
17
|
* Requests to Solr use HTTP POST verb by default to avoid issues when the query string grows too large for GET (Johan Van Ryseghem)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Sunspot
|
2
|
+
#
|
3
|
+
# Keeps a stack of batches and helps out when Indexer is asked to batch documents.
|
4
|
+
#
|
5
|
+
# If the client does something like
|
6
|
+
#
|
7
|
+
# Sunspot.batch do
|
8
|
+
# some_code_here
|
9
|
+
# which_triggers_some_other_code
|
10
|
+
# which_again_calls
|
11
|
+
# Sunspot.batch { ... }
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# it is the Batcher's job to keep track of these nestings. The inner will
|
15
|
+
# be sent of to be indexed first.
|
16
|
+
#
|
17
|
+
class Batcher
|
18
|
+
include Enumerable
|
19
|
+
|
20
|
+
# Raised if you ask to end current, but no current exists
|
21
|
+
class NoCurrentBatchError < StandardError; end
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@stack = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def current
|
28
|
+
@stack.last or start_new
|
29
|
+
end
|
30
|
+
|
31
|
+
def start_new
|
32
|
+
(@stack << []).last
|
33
|
+
end
|
34
|
+
|
35
|
+
def end_current
|
36
|
+
fail NoCurrentBatchError if @stack.empty?
|
37
|
+
|
38
|
+
@stack.pop
|
39
|
+
end
|
40
|
+
|
41
|
+
def depth
|
42
|
+
@stack.length
|
43
|
+
end
|
44
|
+
|
45
|
+
def batching?
|
46
|
+
depth > 0
|
47
|
+
end
|
48
|
+
|
49
|
+
def each(&block)
|
50
|
+
current.each(&block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def push(value)
|
54
|
+
current << value
|
55
|
+
end
|
56
|
+
alias << push
|
57
|
+
|
58
|
+
def concat(values)
|
59
|
+
current.concat values
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -13,6 +13,26 @@ module Sunspot
|
|
13
13
|
@group.limit = num
|
14
14
|
end
|
15
15
|
|
16
|
+
#
|
17
|
+
# If set, facet counts are based on the most relevant document of
|
18
|
+
# each group matching the query.
|
19
|
+
#
|
20
|
+
# Supported in Solr 3.4 and above.
|
21
|
+
#
|
22
|
+
# ==== Example
|
23
|
+
#
|
24
|
+
# Sunspot.search(Post) do
|
25
|
+
# group :title do
|
26
|
+
# truncate
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# facet :title, :extra => :any
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
def truncate
|
33
|
+
@group.truncate = true
|
34
|
+
end
|
35
|
+
|
16
36
|
# Specify the order that results should be returned in. This method can
|
17
37
|
# be called multiple times; precedence will be in the order given.
|
18
38
|
#
|
@@ -185,6 +185,19 @@ module Sunspot
|
|
185
185
|
# semantic meaning is attached to them. The label for +facet+ should be
|
186
186
|
# a symbol; the label for +row+ can be whatever you'd like.
|
187
187
|
#
|
188
|
+
# ==== Range Facets
|
189
|
+
#
|
190
|
+
# One can use the Range Faceting feature on any date field or any numeric
|
191
|
+
# field that supports range queries. This is particularly useful for the
|
192
|
+
# cases in the past where one might stitch together a series of range
|
193
|
+
# queries (as facet by query) for things like prices, etc.
|
194
|
+
#
|
195
|
+
# For example faceting over average ratings can be done as follows:
|
196
|
+
#
|
197
|
+
# Sunspot.search(Post) do
|
198
|
+
# facet :average_rating, :range => 1..5, :range_interval => 1
|
199
|
+
# end
|
200
|
+
#
|
188
201
|
# ==== Parameters
|
189
202
|
#
|
190
203
|
# field_names...<Symbol>:: fields for which to return field facets
|
@@ -195,6 +208,8 @@ module Sunspot
|
|
195
208
|
# Either :count (values matching the most terms first) or :index (lexical)
|
196
209
|
# :limit<Integer>::
|
197
210
|
# The maximum number of facet rows to return
|
211
|
+
# :offset<Integer>::
|
212
|
+
# The offset from which to start returning facet rows
|
198
213
|
# :minimum_count<Integer>::
|
199
214
|
# The minimum count a facet row must have to be returned
|
200
215
|
# :zeros<Boolean>::
|
@@ -276,6 +291,15 @@ module Sunspot
|
|
276
291
|
end
|
277
292
|
search_facet = @search.add_date_facet(field, options)
|
278
293
|
Sunspot::Query::DateFieldFacet.new(field, options)
|
294
|
+
elsif options[:range]
|
295
|
+
unless [Sunspot::Type::TimeType, Sunspot::Type::FloatType, Sunspot::Type::IntegerType ].inject(false){|res,type| res || field.type.is_a?(type)}
|
296
|
+
raise(
|
297
|
+
ArgumentError,
|
298
|
+
':range can only be specified for date or numeric fields'
|
299
|
+
)
|
300
|
+
end
|
301
|
+
search_facet = @search.add_range_facet(field, options)
|
302
|
+
Sunspot::Query::RangeFacet.new(field, options)
|
279
303
|
else
|
280
304
|
search_facet = @search.add_field_facet(field, options)
|
281
305
|
Sunspot::Query::FieldFacet.new(field, options)
|
@@ -130,8 +130,30 @@ module Sunspot
|
|
130
130
|
# :radius<Numeric>::
|
131
131
|
# Radius (in kilometers)
|
132
132
|
#
|
133
|
-
|
134
|
-
|
133
|
+
# ==== Options
|
134
|
+
#
|
135
|
+
# <dt><code>:bbox</code></dt>
|
136
|
+
# <dd>If `true`, performs the search using `bbox`. `bbox` is
|
137
|
+
# more performant, but also more inexact (guaranteed to encompass
|
138
|
+
# all of the points of interest, but may also include other points
|
139
|
+
# that are slightly outside of the required distance).</dd>
|
140
|
+
#
|
141
|
+
def in_radius(lat, lon, radius, options = {})
|
142
|
+
@query.add_geo(Sunspot::Query::Geofilt.new(@field, lat, lon, radius, options))
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# Performs a query that is filtered by a bounding box
|
147
|
+
#
|
148
|
+
# ==== Parameters
|
149
|
+
#
|
150
|
+
# :first_corner<Array>::
|
151
|
+
# First corner (expressed as an array `[latitude, longitude]`)
|
152
|
+
# :second_corner<Array>::
|
153
|
+
# Second corner (expressed as an array `[latitude, longitude]`)
|
154
|
+
#
|
155
|
+
def in_bounding_box(first_corner, second_corner)
|
156
|
+
@query.add_geo(Sunspot::Query::Bbox.new(@field, first_corner, second_corner))
|
135
157
|
end
|
136
158
|
end
|
137
159
|
end
|
data/lib/sunspot/indexer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'sunspot/batcher'
|
2
|
+
|
1
3
|
module Sunspot
|
2
4
|
#
|
3
5
|
# This class presents a service for adding, updating, and removing data
|
@@ -22,10 +24,10 @@ module Sunspot
|
|
22
24
|
#
|
23
25
|
def add(model)
|
24
26
|
documents = Util.Array(model).map { |m| prepare(m) }
|
25
|
-
if
|
26
|
-
|
27
|
+
if batcher.batching?
|
28
|
+
batcher.concat(documents)
|
27
29
|
else
|
28
|
-
|
30
|
+
add_documents(documents)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
@@ -69,19 +71,22 @@ module Sunspot
|
|
69
71
|
# Start batch processing
|
70
72
|
#
|
71
73
|
def start_batch
|
72
|
-
|
74
|
+
batcher.start_new
|
73
75
|
end
|
74
76
|
|
75
77
|
#
|
76
78
|
# Write batch out to Solr and clear it
|
77
79
|
#
|
78
80
|
def flush_batch
|
79
|
-
add_documents(
|
80
|
-
@batch = nil
|
81
|
+
add_documents(batcher.end_current)
|
81
82
|
end
|
82
83
|
|
83
84
|
private
|
84
85
|
|
86
|
+
def batcher
|
87
|
+
@batcher ||= Batcher.new
|
88
|
+
end
|
89
|
+
|
85
90
|
#
|
86
91
|
# Convert documents into hash of indexed properties
|
87
92
|
#
|
data/lib/sunspot/query.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
%w(filter abstract_field_facet connective boost_query date_field_facet dismax
|
1
|
+
%w(filter abstract_field_facet connective boost_query date_field_facet range_facet dismax
|
2
2
|
field_facet highlighting pagination restriction common_query
|
3
|
-
standard_query more_like_this more_like_this_query geo geofilt query_facet
|
4
|
-
sort sort_composite text_field_boost function_query
|
3
|
+
standard_query more_like_this more_like_this_query geo geofilt bbox query_facet
|
4
|
+
scope sort sort_composite text_field_boost function_query
|
5
5
|
composite_fulltext field_group).each do |file|
|
6
6
|
require(File.join(File.dirname(__FILE__), 'query', file))
|
7
7
|
end
|
@@ -26,6 +26,9 @@ module Sunspot
|
|
26
26
|
if @options[:limit]
|
27
27
|
params[qualified_param('limit')] = @options[:limit].to_i
|
28
28
|
end
|
29
|
+
if @options[:offset]
|
30
|
+
params[qualified_param('offset')] = @options[:offset].to_i
|
31
|
+
end
|
29
32
|
if @options[:prefix]
|
30
33
|
params[qualified_param('prefix')] = escape(@options[:prefix].to_s)
|
31
34
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class Bbox
|
4
|
+
def initialize(field, first_corner, second_corner)
|
5
|
+
@field, @first_corner, @second_corner = field, first_corner, second_corner
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_params
|
9
|
+
filter = "#{@field.indexed_name}:[#{@first_corner.join(",")} TO #{@second_corner.join(",")}]"
|
10
|
+
|
11
|
+
{:fq => filter}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -4,7 +4,7 @@ module Sunspot
|
|
4
4
|
# A FieldGroup groups by the unique values of a given field.
|
5
5
|
#
|
6
6
|
class FieldGroup
|
7
|
-
attr_accessor :limit
|
7
|
+
attr_accessor :limit, :truncate
|
8
8
|
|
9
9
|
def initialize(field)
|
10
10
|
if field.multiple?
|
@@ -21,12 +21,14 @@ module Sunspot
|
|
21
21
|
|
22
22
|
def to_params
|
23
23
|
params = {
|
24
|
-
:group
|
25
|
-
:"group.
|
24
|
+
:group => "true",
|
25
|
+
:"group.ngroups" => "true",
|
26
|
+
:"group.field" => @field.indexed_name
|
26
27
|
}
|
27
28
|
|
28
29
|
params.merge!(@sort.to_params("group."))
|
29
30
|
params[:"group.limit"] = @limit if @limit
|
31
|
+
params[:"group.truncate"] = @truncate if @truncate
|
30
32
|
|
31
33
|
params
|
32
34
|
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module Sunspot
|
2
2
|
module Query
|
3
3
|
class Geofilt
|
4
|
-
def initialize(field, lat, lon, radius)
|
5
|
-
@field, @lat, @lon, @radius = field, lat, lon, radius
|
4
|
+
def initialize(field, lat, lon, radius, options = {})
|
5
|
+
@field, @lat, @lon, @radius, @options = field, lat, lon, radius, options
|
6
6
|
end
|
7
7
|
|
8
8
|
def to_params
|
9
|
-
|
9
|
+
func = @options[:bbox] ? "bbox" : "geofilt"
|
10
10
|
|
11
|
+
filter = "{!#{func} sfield=#{@field.indexed_name} pt=#{@lat},#{@lon} d=#{@radius}}"
|
11
12
|
{:fq => filter}
|
12
13
|
end
|
13
14
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class RangeFacet < AbstractFieldFacet
|
4
|
+
def to_params
|
5
|
+
params = super
|
6
|
+
params[:"facet.range"] = [@field.indexed_name]
|
7
|
+
params[qualified_param('range.start')] = @field.to_indexed(@options[:range].first)
|
8
|
+
params[qualified_param('range.end')] = @field.to_indexed(@options[:range].last)
|
9
|
+
params[qualified_param('range.gap')] = "#{@options[:range_interval] || 10}"
|
10
|
+
params
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/sunspot/search.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
%w(abstract_search standard_search more_like_this_search query_facet field_facet
|
2
|
-
date_facet facet_row hit highlight field_group group hit_enumerable).each do |file|
|
2
|
+
date_facet range_facet facet_row hit highlight field_group group hit_enumerable).each do |file|
|
3
3
|
require File.join(File.dirname(__FILE__), 'search', file)
|
4
4
|
end
|
5
5
|
|
@@ -226,6 +226,11 @@ module Sunspot
|
|
226
226
|
add_facet(name, DateFacet.new(field, self, options))
|
227
227
|
end
|
228
228
|
|
229
|
+
def add_range_facet(field, options) #:nodoc:
|
230
|
+
name = (options[:name] || field.name)
|
231
|
+
add_facet(name, RangeFacet.new(field, self, options))
|
232
|
+
end
|
233
|
+
|
229
234
|
def highlights_for(doc) #:nodoc:
|
230
235
|
if @solr_result['highlighting']
|
231
236
|
@solr_result['highlighting'][doc['id']]
|
data/lib/sunspot/search/group.rb
CHANGED
@@ -23,6 +23,10 @@ module Sunspot
|
|
23
23
|
@verified_hits ||= super
|
24
24
|
end
|
25
25
|
|
26
|
+
def results
|
27
|
+
@results ||= verified_hits.map { |hit| hit.instance }
|
28
|
+
end
|
29
|
+
|
26
30
|
def highlights_for(doc)
|
27
31
|
@search.highlights_for(doc)
|
28
32
|
end
|
@@ -30,6 +34,21 @@ module Sunspot
|
|
30
34
|
def solr_docs
|
31
35
|
@doclist['docs']
|
32
36
|
end
|
37
|
+
|
38
|
+
def data_accessor_for(clazz)
|
39
|
+
@search.data_accessor_for(clazz)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# The total number of documents matching the query for this group
|
44
|
+
#
|
45
|
+
# ==== Returns
|
46
|
+
#
|
47
|
+
# Integer:: Total matching documents
|
48
|
+
#
|
49
|
+
def total
|
50
|
+
@doclist['numFound']
|
51
|
+
end
|
33
52
|
end
|
34
53
|
end
|
35
54
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Search
|
3
|
+
class RangeFacet
|
4
|
+
def initialize(field, search, options)
|
5
|
+
@field, @search, @options = field, search, options
|
6
|
+
end
|
7
|
+
|
8
|
+
def field_name
|
9
|
+
@field.name
|
10
|
+
end
|
11
|
+
|
12
|
+
def rows
|
13
|
+
@rows ||=
|
14
|
+
begin
|
15
|
+
data = @search.facet_response['facet_ranges'][@field.indexed_name]
|
16
|
+
gap = (@options[:range_interval] || 10).to_i
|
17
|
+
rows = []
|
18
|
+
|
19
|
+
if data['counts']
|
20
|
+
Hash[*data['counts']].each_pair do |start_str, count|
|
21
|
+
start = start_str.to_f
|
22
|
+
finish = start + gap
|
23
|
+
rows << FacetRow.new(start..finish, count, self)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
if @options[:sort] == :count
|
28
|
+
rows.sort! { |lrow, rrow| rrow.count <=> lrow.count }
|
29
|
+
else
|
30
|
+
rows.sort! { |lrow, rrow| lrow.value.first <=> rrow.value.first }
|
31
|
+
end
|
32
|
+
rows
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/sunspot/session.rb
CHANGED
@@ -239,7 +239,9 @@ module Sunspot
|
|
239
239
|
#
|
240
240
|
def connection
|
241
241
|
@connection ||=
|
242
|
-
self.class.connection_class.connect(:url
|
242
|
+
self.class.connection_class.connect(:url => config.solr.url,
|
243
|
+
:read_timeout => config.solr.read_timeout,
|
244
|
+
:open_timeout => config.solr.open_timeout)
|
243
245
|
end
|
244
246
|
|
245
247
|
def indexer
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'abstract_session_proxy')
|
2
|
+
|
3
|
+
module Sunspot
|
4
|
+
module SessionProxy
|
5
|
+
class Retry5xxSessionProxy < AbstractSessionProxy
|
6
|
+
|
7
|
+
class RetryHandler
|
8
|
+
attr_reader :search_session
|
9
|
+
|
10
|
+
def initialize(search_session)
|
11
|
+
@search_session = search_session
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(m, *args, &block)
|
15
|
+
retry_count = 1
|
16
|
+
begin
|
17
|
+
search_session.send(m, *args, &block)
|
18
|
+
rescue Errno::ECONNRESET => e
|
19
|
+
if retry_count > 0
|
20
|
+
$stderr.puts "Error - #{e.message[/^.*$/]} - retrying..."
|
21
|
+
retry_count -= 1
|
22
|
+
retry
|
23
|
+
else
|
24
|
+
$stderr.puts "Error - #{e.message[/^.*$/]} - ignoring..."
|
25
|
+
end
|
26
|
+
rescue RSolr::Error::Http => e
|
27
|
+
if (500..599).include?(e.response[:status].to_i)
|
28
|
+
if retry_count > 0
|
29
|
+
$stderr.puts "Error - #{e.message[/^.*$/]} - retrying..."
|
30
|
+
retry_count -= 1
|
31
|
+
retry
|
32
|
+
else
|
33
|
+
$stderr.puts "Error - #{e.message[/^.*$/]} - ignoring..."
|
34
|
+
e.response
|
35
|
+
end
|
36
|
+
else
|
37
|
+
raise e
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :search_session
|
44
|
+
attr_reader :retry_handler
|
45
|
+
|
46
|
+
delegate :new_search, :search, :config,
|
47
|
+
:new_more_like_this, :more_like_this,
|
48
|
+
:delete_dirty, :delete_dirty?,
|
49
|
+
:to => :search_session
|
50
|
+
|
51
|
+
def initialize(search_session = Sunspot.session)
|
52
|
+
@search_session = search_session
|
53
|
+
@retry_handler = RetryHandler.new(search_session)
|
54
|
+
end
|
55
|
+
|
56
|
+
def rescued_exception(method, e)
|
57
|
+
$stderr.puts("Exception in #{method}: #{e.message}")
|
58
|
+
end
|
59
|
+
|
60
|
+
delegate :batch, :commit, :commit_if_dirty, :commit_if_delete_dirty,
|
61
|
+
:dirty?, :index!, :index, :optimize, :remove!, :remove, :remove_all!,
|
62
|
+
:remove_all, :remove_by_id!, :remove_by_id,
|
63
|
+
:to => :retry_handler
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/sunspot/version.rb
CHANGED
@@ -0,0 +1,112 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Sunspot::Batcher do
|
4
|
+
it "includes Enumerable" do
|
5
|
+
described_class.should include Enumerable
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#each" do
|
9
|
+
let(:current) { [:foo, :bar] }
|
10
|
+
before { subject.stub(:current).and_return current }
|
11
|
+
|
12
|
+
it "iterates over current" do
|
13
|
+
yielded_values = []
|
14
|
+
|
15
|
+
subject.each do |value|
|
16
|
+
yielded_values << value
|
17
|
+
end
|
18
|
+
|
19
|
+
yielded_values.should eq current
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "adding to current batch" do
|
24
|
+
it "#push pushes to current" do
|
25
|
+
subject.push :foo
|
26
|
+
subject.current.should include :foo
|
27
|
+
end
|
28
|
+
|
29
|
+
it "#<< pushes to current" do
|
30
|
+
subject.push :foo
|
31
|
+
subject.current.should include :foo
|
32
|
+
end
|
33
|
+
|
34
|
+
it "#concat concatinates on current batch" do
|
35
|
+
subject << :foo
|
36
|
+
subject.concat [:bar, :mix]
|
37
|
+
should include :foo, :bar, :mix
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
describe "#current" do
|
43
|
+
context "no current" do
|
44
|
+
it "starts a new" do
|
45
|
+
expect { subject.current }.to change(subject, :depth).by 1
|
46
|
+
end
|
47
|
+
|
48
|
+
it "is empty by default" do
|
49
|
+
subject.current.should be_empty
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with a current" do
|
54
|
+
before { subject.start_new }
|
55
|
+
|
56
|
+
it "does not start a new" do
|
57
|
+
expect { subject.current }.to_not change(subject, :depth)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns the same as last time" do
|
61
|
+
subject.current.should eq subject.current
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#start_new" do
|
67
|
+
it "creates a new batches" do
|
68
|
+
expect { 2.times { subject.start_new } }.to change(subject, :depth).by 2
|
69
|
+
end
|
70
|
+
|
71
|
+
it "changes current" do
|
72
|
+
subject << :foo
|
73
|
+
subject.start_new
|
74
|
+
should_not include :foo
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#end_current" do
|
79
|
+
context "no current batch" do
|
80
|
+
it "fails" do
|
81
|
+
expect { subject.end_current }.to raise_error Sunspot::Batcher::NoCurrentBatchError
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with current batch" do
|
86
|
+
before { subject.start_new }
|
87
|
+
|
88
|
+
it "changes current" do
|
89
|
+
subject << :foo
|
90
|
+
subject.end_current
|
91
|
+
should_not include :foo
|
92
|
+
end
|
93
|
+
|
94
|
+
it "returns current" do
|
95
|
+
subject << :foo
|
96
|
+
subject.end_current.should include :foo
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#batching?" do
|
102
|
+
it "is false when depth is 0" do
|
103
|
+
subject.should_receive(:depth).and_return 0
|
104
|
+
should_not be_batching
|
105
|
+
end
|
106
|
+
|
107
|
+
it "is true when depth is more than 0" do
|
108
|
+
subject.should_receive(:depth).and_return 1
|
109
|
+
should be_batching
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
2
|
|
3
3
|
describe 'batch indexing', :type => :indexer do
|
4
|
+
let(:posts) { Array.new(2) { |index| Post.new :title => "Post number #{index}!" } }
|
5
|
+
|
4
6
|
it 'should send all batched adds in a single request' do
|
5
|
-
posts = Array.new(2) { Post.new }
|
6
7
|
session.batch do
|
7
8
|
for post in posts
|
8
9
|
session.index(post)
|
@@ -12,7 +13,6 @@ describe 'batch indexing', :type => :indexer do
|
|
12
13
|
end
|
13
14
|
|
14
15
|
it 'should add all batched adds' do
|
15
|
-
posts = Array.new(2) { Post.new }
|
16
16
|
session.batch do
|
17
17
|
for post in posts
|
18
18
|
session.index(post)
|
@@ -36,11 +36,37 @@ describe 'batch indexing', :type => :indexer do
|
|
36
36
|
pending 'batching all operations'
|
37
37
|
connection.should_not_receive(:add)
|
38
38
|
connection.should_not_receive(:remove)
|
39
|
-
posts = Array.new(2) { Post.new }
|
40
39
|
session.batch do
|
41
40
|
session.index(posts[0])
|
42
41
|
session.remove(posts[1])
|
43
42
|
end
|
44
43
|
connection.adds
|
45
44
|
end
|
45
|
+
|
46
|
+
describe "nesting of batches" do
|
47
|
+
let(:a_nested_batch) do
|
48
|
+
session.batch do
|
49
|
+
session.index posts[0]
|
50
|
+
|
51
|
+
session.batch do
|
52
|
+
session.index posts[1]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "behaves like two sets of batches, does the inner first, then outer" do
|
58
|
+
session.batch { session.index posts[1] }
|
59
|
+
session.batch { session.index posts[0] }
|
60
|
+
|
61
|
+
two_sets_of_batches_adds = connection.adds.dup
|
62
|
+
connection.adds.clear
|
63
|
+
|
64
|
+
a_nested_batch
|
65
|
+
nested_batches_adds = connection.adds
|
66
|
+
|
67
|
+
nested_batches_adds.first.first.field_by_name(:title_ss).value.should eq(
|
68
|
+
two_sets_of_batches_adds.first.first.field_by_name(:title_ss).value
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
46
72
|
end
|
@@ -54,6 +54,13 @@ shared_examples_for "facetable query" do
|
|
54
54
|
end
|
55
55
|
connection.should have_last_search_with(:"f.category_ids_im.facet.limit" => 10)
|
56
56
|
end
|
57
|
+
|
58
|
+
it 'sets the facet offset' do
|
59
|
+
search do
|
60
|
+
facet :category_ids, :offset => 10
|
61
|
+
end
|
62
|
+
connection.should have_last_search_with(:"f.category_ids_im.facet.offset" => 10)
|
63
|
+
end
|
57
64
|
|
58
65
|
it 'sets the facet minimum count' do
|
59
66
|
search do
|
@@ -255,6 +262,58 @@ shared_examples_for "facetable query" do
|
|
255
262
|
end
|
256
263
|
end
|
257
264
|
|
265
|
+
describe 'on range facets' do
|
266
|
+
before :each do
|
267
|
+
@range = 2..4
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'does not send range facet parameters if integer range is not specified' do
|
271
|
+
search do |query|
|
272
|
+
query.facet :average_rating
|
273
|
+
end
|
274
|
+
connection.should_not have_last_search_with(:"facet.range")
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'sets the facet to a range facet if the range is specified' do
|
278
|
+
search do |query|
|
279
|
+
query.facet :average_rating, :range => @range
|
280
|
+
end
|
281
|
+
connection.should have_last_search_with(:"facet.range" => ['average_rating_ft'])
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'sets the facet start and end' do
|
285
|
+
search do |query|
|
286
|
+
query.facet :average_rating, :range => @range
|
287
|
+
end
|
288
|
+
connection.should have_last_search_with(
|
289
|
+
:"f.average_rating_ft.facet.range.start" => '2.0',
|
290
|
+
:"f.average_rating_ft.facet.range.end" => '4.0'
|
291
|
+
)
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'defaults the range interval to 10' do
|
295
|
+
search do |query|
|
296
|
+
query.facet :average_rating, :range => @range
|
297
|
+
end
|
298
|
+
connection.should have_last_search_with(:"f.average_rating_ft.facet.range.gap" => "10")
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'uses custom range interval' do
|
302
|
+
search do |query|
|
303
|
+
query.facet :average_rating, :range => @range, :range_interval => 1
|
304
|
+
end
|
305
|
+
connection.should have_last_search_with(:"f.average_rating_ft.facet.range.gap" => "1")
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'does not allow date faceting on a non-continuous field' do
|
309
|
+
lambda do
|
310
|
+
search do |query|
|
311
|
+
query.facet :title, :range => @range
|
312
|
+
end
|
313
|
+
end.should raise_error(ArgumentError)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
258
317
|
describe 'using queries' do
|
259
318
|
it 'turns faceting on' do
|
260
319
|
search do
|
@@ -8,4 +8,20 @@ shared_examples_for "spatial query" do
|
|
8
8
|
|
9
9
|
connection.should have_last_search_including(:fq, "{!geofilt sfield=coordinates_new_ll pt=23,-46 d=100}")
|
10
10
|
end
|
11
|
+
|
12
|
+
it 'filters by radius via bbox (inexact)' do
|
13
|
+
search do
|
14
|
+
with(:coordinates_new).in_radius(23, -46, 100, :bbox => true)
|
15
|
+
end
|
16
|
+
|
17
|
+
connection.should have_last_search_including(:fq, "{!bbox sfield=coordinates_new_ll pt=23,-46 d=100}")
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'filters by bounding box' do
|
21
|
+
search do
|
22
|
+
with(:coordinates_new).in_bounding_box([45, -94], [46, -93])
|
23
|
+
end
|
24
|
+
|
25
|
+
connection.should have_last_search_including(:fq, "coordinates_new_ll:[45,-94 TO 46,-93]")
|
26
|
+
end
|
11
27
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe Sunspot::SessionProxy::Retry5xxSessionProxy do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
Sunspot::Session.connection_class = Mock::ConnectionFactory.new
|
7
|
+
@sunspot_session = Sunspot.session
|
8
|
+
@proxy = Sunspot::SessionProxy::Retry5xxSessionProxy.new(@sunspot_session)
|
9
|
+
Sunspot.session = @proxy
|
10
|
+
end
|
11
|
+
|
12
|
+
class FakeRSolrErrorHttp < RSolr::Error::Http
|
13
|
+
def backtrace
|
14
|
+
[]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let :fake_rsolr_request do
|
19
|
+
{:uri => 'http://solr.test/uri'}
|
20
|
+
end
|
21
|
+
|
22
|
+
def fake_rsolr_response(status)
|
23
|
+
{:status => status.to_s}
|
24
|
+
end
|
25
|
+
|
26
|
+
let :post do
|
27
|
+
Post.new(:title => 'test')
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should behave normally without a stubbed exception" do
|
31
|
+
@sunspot_session.should_receive(:index).and_return(mock)
|
32
|
+
Sunspot.index(post)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be successful with a single exception followed by a sucess" do
|
36
|
+
e = FakeRSolrErrorHttp.new(fake_rsolr_request, fake_rsolr_response(503))
|
37
|
+
@sunspot_session.should_receive(:index).and_return do
|
38
|
+
@sunspot_session.should_receive(:index).and_return(mock)
|
39
|
+
raise e
|
40
|
+
end
|
41
|
+
Sunspot.index(post)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return the error response after two exceptions" do
|
45
|
+
fake_response = fake_rsolr_response(503)
|
46
|
+
e = FakeRSolrErrorHttp.new(fake_rsolr_request, fake_response)
|
47
|
+
fake_success = mock('success')
|
48
|
+
|
49
|
+
@sunspot_session.should_receive(:index).and_return do
|
50
|
+
@sunspot_session.should_receive(:index).and_return do
|
51
|
+
@sunspot_session.stub!(:index).and_return(fake_success)
|
52
|
+
raise e
|
53
|
+
end
|
54
|
+
raise e
|
55
|
+
end
|
56
|
+
|
57
|
+
response = Sunspot.index(post)
|
58
|
+
response.should_not == fake_success
|
59
|
+
response.should == fake_response
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should not retry a 4xx" do
|
63
|
+
e = FakeRSolrErrorHttp.new(fake_rsolr_request, fake_rsolr_response(400))
|
64
|
+
@sunspot_session.should_receive(:index).and_raise(e)
|
65
|
+
lambda { Sunspot.index(post) }.should raise_error
|
66
|
+
end
|
67
|
+
|
68
|
+
# TODO: try against more than just Sunspot.index? but that's just testing the
|
69
|
+
# invocation of delegate, so probably not important. -nz 11Apr12
|
70
|
+
|
71
|
+
it_should_behave_like 'session proxy'
|
72
|
+
|
73
|
+
end
|
data/spec/api/session_spec.rb
CHANGED
@@ -85,6 +85,18 @@ describe 'Session' do
|
|
85
85
|
Sunspot.commit
|
86
86
|
connection.opts[:url].should == 'http://127.0.0.1:8981/solr'
|
87
87
|
end
|
88
|
+
|
89
|
+
it 'should open a connection with custom read timeout' do
|
90
|
+
Sunspot.config.solr.read_timeout = 0.5
|
91
|
+
Sunspot.commit
|
92
|
+
connection.opts[:read_timeout].should == 0.5
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should open a connection with custom open timeout' do
|
96
|
+
Sunspot.config.solr.open_timeout = 0.5
|
97
|
+
Sunspot.commit
|
98
|
+
connection.opts[:open_timeout].should == 0.5
|
99
|
+
end
|
88
100
|
end
|
89
101
|
|
90
102
|
context 'custom session' do
|
@@ -84,6 +84,13 @@ describe 'search faceting' do
|
|
84
84
|
end
|
85
85
|
search.facet(:title).rows.map { |row| row.value }.should include('zero')
|
86
86
|
end
|
87
|
+
|
88
|
+
it 'should return facet rows from an offset' do
|
89
|
+
search = Sunspot.search(Post) do
|
90
|
+
facet :title, :offset => 3
|
91
|
+
end
|
92
|
+
search.facet(:title).rows.map { |row| row.value }.should == %w(one zero)
|
93
|
+
end
|
87
94
|
|
88
95
|
it 'should return a specified minimum count' do
|
89
96
|
search = Sunspot.search(Post) do
|
@@ -134,6 +141,19 @@ describe 'search faceting' do
|
|
134
141
|
search.facet(:title).rows.first.value.should == :none
|
135
142
|
search.facet(:title).rows.first.count.should == 1
|
136
143
|
end
|
144
|
+
|
145
|
+
it 'gives correct facet count when group == true and truncate == true' do
|
146
|
+
search = Sunspot.search(Post) do
|
147
|
+
group :title do
|
148
|
+
truncate
|
149
|
+
end
|
150
|
+
|
151
|
+
facet :title, :extra => :any
|
152
|
+
end
|
153
|
+
|
154
|
+
# Should be 5 instead of 11
|
155
|
+
search.facet(:title).rows.first.count.should == 5
|
156
|
+
end
|
137
157
|
end
|
138
158
|
|
139
159
|
context 'multiselect faceting' do
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.expand_path("../spec_helper", File.dirname(__FILE__))
|
2
|
+
require File.expand_path("../helpers/search_helper", File.dirname(__FILE__))
|
2
3
|
|
3
4
|
describe "field grouping" do
|
4
5
|
before :each do
|
@@ -22,6 +23,14 @@ describe "field grouping" do
|
|
22
23
|
search.group(:title).groups.should include { |g| g.value == "Title2" }
|
23
24
|
end
|
24
25
|
|
26
|
+
it "returns the number of matches unique groups" do
|
27
|
+
search = Sunspot.search(Post) do
|
28
|
+
group :title
|
29
|
+
end
|
30
|
+
|
31
|
+
search.group(:title).total.should == 2
|
32
|
+
end
|
33
|
+
|
25
34
|
it "provides access to the number of matches before grouping" do
|
26
35
|
search = Sunspot.search(Post) do
|
27
36
|
group :title
|
@@ -10,7 +10,7 @@ describe "geospatial search" do
|
|
10
10
|
Sunspot.index!(@post)
|
11
11
|
end
|
12
12
|
|
13
|
-
it "matches posts
|
13
|
+
it "matches posts within the radius" do
|
14
14
|
results = Sunspot.search(Post) {
|
15
15
|
with(:coordinates_new).in_radius(32, -68, 1)
|
16
16
|
}.results
|
@@ -27,6 +27,32 @@ describe "geospatial search" do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
describe "filtering by bounding box" do
|
31
|
+
before :all do
|
32
|
+
Sunspot.remove_all
|
33
|
+
|
34
|
+
@post = Post.new(:title => "Howdy",
|
35
|
+
:coordinates => Sunspot::Util::Coordinates.new(32, -68))
|
36
|
+
Sunspot.index!(@post)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "matches post within the bounding box" do
|
40
|
+
results = Sunspot.search(Post) {
|
41
|
+
with(:coordinates_new).in_bounding_box [31, -69], [33, -67]
|
42
|
+
}.results
|
43
|
+
|
44
|
+
results.should include(@post)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "filters out posts not in the bounding box" do
|
48
|
+
results = Sunspot.search(Post) {
|
49
|
+
with(:coordinates_new).in_bounding_box [20, -70], [21, -69]
|
50
|
+
}.results
|
51
|
+
|
52
|
+
results.should_not include(@post)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
30
56
|
describe "ordering by geodist" do
|
31
57
|
before :all do
|
32
58
|
Sunspot.remove_all
|
@@ -30,4 +30,26 @@ describe 'indexing' do
|
|
30
30
|
end
|
31
31
|
Sunspot.search(Post).should have(2).results
|
32
32
|
end
|
33
|
+
|
34
|
+
|
35
|
+
describe "in batches" do
|
36
|
+
let(:post_1) { Post.new :title => 'A tittle' }
|
37
|
+
let(:post_2) { Post.new :title => 'Another title' }
|
38
|
+
|
39
|
+
describe "nested" do
|
40
|
+
let(:a_nested_batch) do
|
41
|
+
Sunspot.batch do
|
42
|
+
Sunspot.index post_1
|
43
|
+
|
44
|
+
Sunspot.batch do
|
45
|
+
Sunspot.index post_2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not fail" do
|
51
|
+
expect { a_nested_batch }.to_not raise_error
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
33
55
|
end
|
data/sunspot.gemspec
CHANGED
@@ -25,8 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
26
|
s.require_paths = ["lib"]
|
27
27
|
|
28
|
-
s.add_dependency 'rsolr', '~>1.0.
|
29
|
-
s.add_dependency 'escape', '~>0.0.4'
|
28
|
+
s.add_dependency 'rsolr', '~>1.0.7'
|
30
29
|
s.add_dependency 'pr_geohash', '~>1.0'
|
31
30
|
|
32
31
|
s.add_development_dependency 'rspec', '~>2.6.0'
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sunspot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: -2204637468
|
5
|
+
prerelease: 6
|
5
6
|
segments:
|
6
7
|
- 2
|
7
8
|
- 0
|
8
9
|
- 0
|
9
10
|
- pre
|
10
|
-
-
|
11
|
-
version: 2.0.0.pre.
|
11
|
+
- 120415
|
12
|
+
version: 2.0.0.pre.120415
|
12
13
|
platform: ruby
|
13
14
|
authors:
|
14
15
|
- Mat Brown
|
@@ -34,76 +35,69 @@ autorequire:
|
|
34
35
|
bindir: bin
|
35
36
|
cert_chain: []
|
36
37
|
|
37
|
-
date:
|
38
|
-
default_executable:
|
38
|
+
date: 2012-04-15 00:00:00 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: rsolr
|
42
42
|
prerelease: false
|
43
43
|
requirement: &id001 !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
44
45
|
requirements:
|
45
46
|
- - ~>
|
46
47
|
- !ruby/object:Gem::Version
|
48
|
+
hash: 25
|
47
49
|
segments:
|
48
50
|
- 1
|
49
51
|
- 0
|
50
|
-
-
|
51
|
-
version: 1.0.
|
52
|
+
- 7
|
53
|
+
version: 1.0.7
|
52
54
|
type: :runtime
|
53
55
|
version_requirements: *id001
|
54
|
-
- !ruby/object:Gem::Dependency
|
55
|
-
name: escape
|
56
|
-
prerelease: false
|
57
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
segments:
|
62
|
-
- 0
|
63
|
-
- 0
|
64
|
-
- 4
|
65
|
-
version: 0.0.4
|
66
|
-
type: :runtime
|
67
|
-
version_requirements: *id002
|
68
56
|
- !ruby/object:Gem::Dependency
|
69
57
|
name: pr_geohash
|
70
58
|
prerelease: false
|
71
|
-
requirement: &
|
59
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
72
61
|
requirements:
|
73
62
|
- - ~>
|
74
63
|
- !ruby/object:Gem::Version
|
64
|
+
hash: 15
|
75
65
|
segments:
|
76
66
|
- 1
|
77
67
|
- 0
|
78
68
|
version: "1.0"
|
79
69
|
type: :runtime
|
80
|
-
version_requirements: *
|
70
|
+
version_requirements: *id002
|
81
71
|
- !ruby/object:Gem::Dependency
|
82
72
|
name: rspec
|
83
73
|
prerelease: false
|
84
|
-
requirement: &
|
74
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
85
76
|
requirements:
|
86
77
|
- - ~>
|
87
78
|
- !ruby/object:Gem::Version
|
79
|
+
hash: 23
|
88
80
|
segments:
|
89
81
|
- 2
|
90
82
|
- 6
|
91
83
|
- 0
|
92
84
|
version: 2.6.0
|
93
85
|
type: :development
|
94
|
-
version_requirements: *
|
86
|
+
version_requirements: *id003
|
95
87
|
- !ruby/object:Gem::Dependency
|
96
88
|
name: hanna
|
97
89
|
prerelease: false
|
98
|
-
requirement: &
|
90
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
99
92
|
requirements:
|
100
93
|
- - ">="
|
101
94
|
- !ruby/object:Gem::Version
|
95
|
+
hash: 3
|
102
96
|
segments:
|
103
97
|
- 0
|
104
98
|
version: "0"
|
105
99
|
type: :development
|
106
|
-
version_requirements: *
|
100
|
+
version_requirements: *id004
|
107
101
|
description: " Sunspot is a library providing a powerful, all-ruby API for the Solr search engine. Sunspot manages the configuration of persistent\n Ruby classes for search and indexing and exposes Solr's most powerful features through a collection of DSLs. Complex search operations\n can be performed without hand-writing any boolean queries or building Solr parameters by hand.\n"
|
108
102
|
email:
|
109
103
|
- mat@patch.com
|
@@ -123,6 +117,7 @@ files:
|
|
123
117
|
- lib/light_config.rb
|
124
118
|
- lib/sunspot.rb
|
125
119
|
- lib/sunspot/adapters.rb
|
120
|
+
- lib/sunspot/batcher.rb
|
126
121
|
- lib/sunspot/class_set.rb
|
127
122
|
- lib/sunspot/composite_setup.rb
|
128
123
|
- lib/sunspot/configuration.rb
|
@@ -148,6 +143,7 @@ files:
|
|
148
143
|
- lib/sunspot/indexer.rb
|
149
144
|
- lib/sunspot/query.rb
|
150
145
|
- lib/sunspot/query/abstract_field_facet.rb
|
146
|
+
- lib/sunspot/query/bbox.rb
|
151
147
|
- lib/sunspot/query/boost_query.rb
|
152
148
|
- lib/sunspot/query/common_query.rb
|
153
149
|
- lib/sunspot/query/composite_fulltext.rb
|
@@ -165,6 +161,7 @@ files:
|
|
165
161
|
- lib/sunspot/query/more_like_this_query.rb
|
166
162
|
- lib/sunspot/query/pagination.rb
|
167
163
|
- lib/sunspot/query/query_facet.rb
|
164
|
+
- lib/sunspot/query/range_facet.rb
|
168
165
|
- lib/sunspot/query/restriction.rb
|
169
166
|
- lib/sunspot/query/scope.rb
|
170
167
|
- lib/sunspot/query/sort.rb
|
@@ -185,6 +182,7 @@ files:
|
|
185
182
|
- lib/sunspot/search/more_like_this_search.rb
|
186
183
|
- lib/sunspot/search/paginated_collection.rb
|
187
184
|
- lib/sunspot/search/query_facet.rb
|
185
|
+
- lib/sunspot/search/range_facet.rb
|
188
186
|
- lib/sunspot/search/standard_search.rb
|
189
187
|
- lib/sunspot/session.rb
|
190
188
|
- lib/sunspot/session_proxy.rb
|
@@ -192,6 +190,7 @@ files:
|
|
192
190
|
- lib/sunspot/session_proxy/class_sharding_session_proxy.rb
|
193
191
|
- lib/sunspot/session_proxy/id_sharding_session_proxy.rb
|
194
192
|
- lib/sunspot/session_proxy/master_slave_session_proxy.rb
|
193
|
+
- lib/sunspot/session_proxy/retry_5xx_session_proxy.rb
|
195
194
|
- lib/sunspot/session_proxy/sharding_session_proxy.rb
|
196
195
|
- lib/sunspot/session_proxy/silent_fail_session_proxy.rb
|
197
196
|
- lib/sunspot/session_proxy/thread_local_session_proxy.rb
|
@@ -204,6 +203,7 @@ files:
|
|
204
203
|
- pkg/.gitignore
|
205
204
|
- script/console
|
206
205
|
- spec/api/adapters_spec.rb
|
206
|
+
- spec/api/batcher_spec.rb
|
207
207
|
- spec/api/binding_spec.rb
|
208
208
|
- spec/api/class_set_spec.rb
|
209
209
|
- spec/api/hit_enumerable_spec.rb
|
@@ -244,6 +244,7 @@ files:
|
|
244
244
|
- spec/api/session_proxy/class_sharding_session_proxy_spec.rb
|
245
245
|
- spec/api/session_proxy/id_sharding_session_proxy_spec.rb
|
246
246
|
- spec/api/session_proxy/master_slave_session_proxy_spec.rb
|
247
|
+
- spec/api/session_proxy/retry_5xx_session_proxy_spec.rb
|
247
248
|
- spec/api/session_proxy/sharding_session_proxy_spec.rb
|
248
249
|
- spec/api/session_proxy/silent_fail_session_proxy_spec.rb
|
249
250
|
- spec/api/session_proxy/spec_helper.rb
|
@@ -287,7 +288,6 @@ files:
|
|
287
288
|
- tasks/rdoc.rake
|
288
289
|
- tasks/schema.rake
|
289
290
|
- tasks/todo.rake
|
290
|
-
has_rdoc: true
|
291
291
|
homepage: http://outoftime.github.com/sunspot
|
292
292
|
licenses: []
|
293
293
|
|
@@ -301,16 +301,20 @@ rdoc_options:
|
|
301
301
|
require_paths:
|
302
302
|
- lib
|
303
303
|
required_ruby_version: !ruby/object:Gem::Requirement
|
304
|
+
none: false
|
304
305
|
requirements:
|
305
306
|
- - ">="
|
306
307
|
- !ruby/object:Gem::Version
|
308
|
+
hash: 3
|
307
309
|
segments:
|
308
310
|
- 0
|
309
311
|
version: "0"
|
310
312
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
313
|
+
none: false
|
311
314
|
requirements:
|
312
315
|
- - ">"
|
313
316
|
- !ruby/object:Gem::Version
|
317
|
+
hash: 25
|
314
318
|
segments:
|
315
319
|
- 1
|
316
320
|
- 3
|
@@ -319,12 +323,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
319
323
|
requirements: []
|
320
324
|
|
321
325
|
rubyforge_project: sunspot
|
322
|
-
rubygems_version: 1.
|
326
|
+
rubygems_version: 1.8.15
|
323
327
|
signing_key:
|
324
328
|
specification_version: 3
|
325
329
|
summary: Library for expressive, powerful interaction with the Solr search engine
|
326
330
|
test_files:
|
327
331
|
- spec/api/adapters_spec.rb
|
332
|
+
- spec/api/batcher_spec.rb
|
328
333
|
- spec/api/binding_spec.rb
|
329
334
|
- spec/api/class_set_spec.rb
|
330
335
|
- spec/api/hit_enumerable_spec.rb
|
@@ -365,6 +370,7 @@ test_files:
|
|
365
370
|
- spec/api/session_proxy/class_sharding_session_proxy_spec.rb
|
366
371
|
- spec/api/session_proxy/id_sharding_session_proxy_spec.rb
|
367
372
|
- spec/api/session_proxy/master_slave_session_proxy_spec.rb
|
373
|
+
- spec/api/session_proxy/retry_5xx_session_proxy_spec.rb
|
368
374
|
- spec/api/session_proxy/sharding_session_proxy_spec.rb
|
369
375
|
- spec/api/session_proxy/silent_fail_session_proxy_spec.rb
|
370
376
|
- spec/api/session_proxy/spec_helper.rb
|