sunspot 2.2.8 → 2.3.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.
- checksums.yaml +5 -5
- data/lib/sunspot/configuration.rb +1 -0
- data/lib/sunspot/dsl/field_query.rb +11 -0
- data/lib/sunspot/dsl/field_stats.rb +7 -0
- data/lib/sunspot/query.rb +3 -3
- data/lib/sunspot/query/abstract_json_field_facet.rb +70 -0
- data/lib/sunspot/query/date_field_json_facet.rb +25 -0
- data/lib/sunspot/query/field_json_facet.rb +19 -0
- data/lib/sunspot/query/field_stats.rb +35 -2
- data/lib/sunspot/query/range_json_facet.rb +28 -0
- data/lib/sunspot/schema.rb +10 -2
- data/lib/sunspot/search.rb +4 -3
- data/lib/sunspot/search/abstract_search.rb +13 -0
- data/lib/sunspot/search/field_json_facet.rb +33 -0
- data/lib/sunspot/search/json_facet_row.rb +40 -0
- data/lib/sunspot/search/json_facet_stats.rb +23 -0
- data/lib/sunspot/search/stats_json_row.rb +82 -0
- data/lib/sunspot/search/stats_row.rb +3 -1
- data/lib/sunspot/session.rb +7 -5
- data/lib/sunspot/util.rb +23 -0
- data/lib/sunspot/version.rb +1 -1
- data/spec/api/query/fulltext_examples.rb +16 -6
- data/spec/helpers/integration_helper.rb +1 -0
- data/spec/integration/faceting_spec.rb +213 -0
- data/spec/integration/scoped_search_spec.rb +1 -1
- data/spec/integration/stats_spec.rb +44 -3
- data/spec/mocks/post.rb +4 -0
- data/spec/spec_helper.rb +2 -6
- data/sunspot.gemspec +1 -1
- metadata +15 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 698b438f344a3e391c87d9f755dc227869fefad88555b261ef4dcd9cc9d9c1d1
|
4
|
+
data.tar.gz: 2ba1b782a43a5eafd6f1bc6397ef221fe94bbbb92f1036505530719a50f07882
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f89e196fd125f6c0b2bd8eda2aecf7c288860ff14ab128d695f61252344fc07b0011ed8c10d8c5578227eae814df368fecf3332d306ae2a79e9b5da593dfc97
|
7
|
+
data.tar.gz: 780ca66b8d6e569a994670b2e6f990444333dc03f109bd015c7f26924673e801281f611f5d08b14b48afb35b6177099747113e0bbdc10a07aebe4cee5f93c8ea
|
@@ -333,6 +333,17 @@ module Sunspot
|
|
333
333
|
end
|
334
334
|
end
|
335
335
|
|
336
|
+
def json_facet(*field_names)
|
337
|
+
options = Sunspot::Util.extract_options_from(field_names)
|
338
|
+
|
339
|
+
field_names.each do |field_name|
|
340
|
+
field = @setup.field(field_name)
|
341
|
+
facet = Sunspot::Util.parse_json_facet(field_name, options, @setup)
|
342
|
+
@search.add_json_facet(field, options)
|
343
|
+
@query.add_query_facet(facet)
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
336
347
|
def stats(*field_names, &block)
|
337
348
|
options = Sunspot::Util.extract_options_from(field_names)
|
338
349
|
|
@@ -13,6 +13,13 @@ module Sunspot
|
|
13
13
|
@search_stats.add_facet(field)
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
def json_facet(field_name, options = {})
|
18
|
+
field = @setup.field(field_name)
|
19
|
+
facet = Sunspot::Util.parse_json_facet(field_name, options, @setup)
|
20
|
+
@query_stats.add_json_facet(facet)
|
21
|
+
end
|
22
|
+
|
16
23
|
end
|
17
24
|
end
|
18
25
|
end
|
data/lib/sunspot/query.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
%w(filter abstract_field_facet connective boost_query date_field_facet
|
2
|
-
range_facet abstract_fulltext dismax join
|
3
|
-
field_facet highlighting pagination restriction common_query spellcheck
|
1
|
+
%w(filter abstract_field_facet abstract_json_field_facet connective boost_query date_field_facet field_json_facet
|
2
|
+
range_facet range_json_facet date_field_json_facet abstract_fulltext dismax join
|
3
|
+
field_list field_facet highlighting pagination restriction common_query spellcheck
|
4
4
|
standard_query more_like_this more_like_this_query geo geofilt bbox query_facet
|
5
5
|
scope sort sort_composite text_field_boost function_query field_stats
|
6
6
|
composite_fulltext group group_query).each do |file|
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class AbstractJsonFieldFacet
|
4
|
+
|
5
|
+
attr_accessor :field
|
6
|
+
|
7
|
+
DISTINCT_STRATEGIES = [:unique, :hll]
|
8
|
+
|
9
|
+
def initialize(field, options, setup)
|
10
|
+
@field, @options, @setup = field, options, setup
|
11
|
+
end
|
12
|
+
|
13
|
+
def init_params
|
14
|
+
params = {}
|
15
|
+
params[:limit] = @options[:limit] unless @options[:limit].nil?
|
16
|
+
params[:mincount] = @options[:minimum_count] unless @options[:minimum_count].nil?
|
17
|
+
params[:sort] = { @options[:sort] => @options[:sort_type]||'desc' } unless @options[:sort].nil?
|
18
|
+
params[:prefix] = @options[:prefix] unless @options[:prefix].nil?
|
19
|
+
params[:offset] = @options[:offset] unless @options[:offset].nil?
|
20
|
+
|
21
|
+
if !@options[:distinct].nil?
|
22
|
+
dist_opts = @options[:distinct]
|
23
|
+
raise Exception.new("Need to specify a strategy") if dist_opts[:strategy].nil?
|
24
|
+
raise Exception.new("The strategy must be one of #{DISTINCT_STRATEGIES}") unless DISTINCT_STRATEGIES.include?(dist_opts[:strategy])
|
25
|
+
@stategy = dist_opts[:strategy]
|
26
|
+
@group_by = dist_opts[:group_by].nil? ? @field : @setup.field(dist_opts[:group_by])
|
27
|
+
params[:field] = @group_by.indexed_name
|
28
|
+
params[:facet] = {}
|
29
|
+
params[:facet][:distinct] = "#{@stategy}(#{@field.indexed_name})"
|
30
|
+
end
|
31
|
+
|
32
|
+
params
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_params
|
36
|
+
query = field_name_with_local_params
|
37
|
+
nested_params = recursive_nested_params(@options)
|
38
|
+
|
39
|
+
if !nested_params.nil?
|
40
|
+
query[@field.name][:facet] ||= {}
|
41
|
+
query[@field.name][:facet].merge!(nested_params)
|
42
|
+
end
|
43
|
+
query
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_params
|
47
|
+
{ 'json.facet' => self.get_params.to_json }
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def recursive_nested_params(options)
|
53
|
+
if !options[:nested].nil? && options[:nested].is_a?(Hash)
|
54
|
+
opts = options[:nested]
|
55
|
+
field_name = opts[:field]
|
56
|
+
|
57
|
+
options = Sunspot::Util.extract_options_from([opts])
|
58
|
+
params = Sunspot::Util.parse_json_facet(field_name, options, @setup).field_name_with_local_params
|
59
|
+
if !opts.nil?
|
60
|
+
nested_params = recursive_nested_params(opts)
|
61
|
+
params[field_name][:facet] = nested_params unless nested_params.nil?
|
62
|
+
end
|
63
|
+
|
64
|
+
params
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class DateFieldJsonFacet < AbstractJsonFieldFacet
|
4
|
+
|
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
|
+
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 }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class FieldJsonFacet < AbstractJsonFieldFacet
|
4
|
+
|
5
|
+
def initialize(field, options, setup)
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def field_name_with_local_params
|
10
|
+
{
|
11
|
+
@field.name => {
|
12
|
+
type: 'terms',
|
13
|
+
field: @field.indexed_name,
|
14
|
+
}.merge!(init_params)
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -10,9 +10,42 @@ module Sunspot
|
|
10
10
|
@facets << field
|
11
11
|
end
|
12
12
|
|
13
|
+
def add_json_facet(json_facet)
|
14
|
+
@json_facet = json_facet
|
15
|
+
end
|
16
|
+
|
13
17
|
def to_params
|
14
|
-
params = {
|
15
|
-
|
18
|
+
params = {}
|
19
|
+
if !@json_facet.nil?
|
20
|
+
params['json.facet'] = recursive_add_stats(@json_facet.get_params).to_json
|
21
|
+
else
|
22
|
+
params.merge!(:stats => true, :"stats.field" => [@field.indexed_name])
|
23
|
+
params[facet_key] = @facets.map(&:indexed_name) unless @facets.empty?
|
24
|
+
end
|
25
|
+
params
|
26
|
+
end
|
27
|
+
|
28
|
+
STATS_FUNCTIONS = [:min, :max, :sum, :avg, :sumsq]
|
29
|
+
|
30
|
+
def recursive_add_stats(query)
|
31
|
+
query.keys.each do |k|
|
32
|
+
if !query[k][:facet].nil?
|
33
|
+
query[k][:facet] = recursive_add_stats(query[k][:facet])
|
34
|
+
end
|
35
|
+
query[k][:facet] ||= {}
|
36
|
+
query[k][:sort] = { @options[:sort] => @options[:sort_type]||'desc' } unless @options[:sort].nil?
|
37
|
+
query[k][:facet].merge!(json_stats_params)
|
38
|
+
end
|
39
|
+
query
|
40
|
+
end
|
41
|
+
|
42
|
+
def json_stats_params
|
43
|
+
params = {}
|
44
|
+
STATS_FUNCTIONS.each { |s| params[s] = "#{s.to_s}(#{@field.indexed_name})" }
|
45
|
+
unless @options[:stats].nil?
|
46
|
+
to_remove = STATS_FUNCTIONS - @options[:stats]
|
47
|
+
to_remove.map { |s| params.delete(s)}
|
48
|
+
end
|
16
49
|
params
|
17
50
|
end
|
18
51
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class RangeJsonFacet < AbstractJsonFieldFacet
|
4
|
+
|
5
|
+
SECONDS_IN_DAY = 86400
|
6
|
+
|
7
|
+
def initialize(field, options, setup)
|
8
|
+
raise Exception.new("Need to specify a range") if options[:range].nil?
|
9
|
+
@start = options[:range].first
|
10
|
+
@end = options[:range].last
|
11
|
+
@gap = options[:gap] || SECONDS_IN_DAY
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def field_name_with_local_params
|
16
|
+
{
|
17
|
+
@field.name => {
|
18
|
+
type: 'range',
|
19
|
+
field: @field.indexed_name,
|
20
|
+
start: @field.to_indexed(@start),
|
21
|
+
end: @field.to_indexed(@end),
|
22
|
+
gap: @gap
|
23
|
+
}.merge!(init_params)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/sunspot/schema.rb
CHANGED
@@ -88,8 +88,16 @@ module Sunspot
|
|
88
88
|
# Return an XML representation of this schema using the ERB template
|
89
89
|
#
|
90
90
|
def to_xml
|
91
|
-
|
92
|
-
|
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)
|
93
101
|
end
|
94
102
|
|
95
103
|
private
|
data/lib/sunspot/search.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
%w(abstract_search standard_search more_like_this_search query_facet
|
2
|
-
date_facet range_facet
|
3
|
-
|
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|
|
4
5
|
require File.join(File.dirname(__FILE__), 'search', file)
|
5
6
|
end
|
6
7
|
|
@@ -182,6 +182,10 @@ module Sunspot
|
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
|
+
def json_facet_stats(name, options = {})
|
186
|
+
JsonFacetStats.new(name, self, options)
|
187
|
+
end
|
188
|
+
|
185
189
|
#
|
186
190
|
# Deprecated in favor of optional second argument to #facet
|
187
191
|
#
|
@@ -193,6 +197,10 @@ module Sunspot
|
|
193
197
|
@solr_result['facet_counts']
|
194
198
|
end
|
195
199
|
|
200
|
+
def json_facet_response #:nodoc:
|
201
|
+
@solr_result['facets']
|
202
|
+
end
|
203
|
+
|
196
204
|
def stats_response #:nodoc:
|
197
205
|
@solr_result['stats']['stats_fields']
|
198
206
|
end
|
@@ -255,6 +263,11 @@ module Sunspot
|
|
255
263
|
add_stats(field.name, FieldStats.new(field, self))
|
256
264
|
end
|
257
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
|
+
|
258
271
|
def highlights_for(doc) #:nodoc:
|
259
272
|
if @solr_result['highlighting']
|
260
273
|
@solr_result['highlighting'][doc['id']]
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Search
|
3
|
+
class FieldJsonFacet
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(field, search, options)
|
8
|
+
@name, @search, @options = name, search, options
|
9
|
+
@field = field
|
10
|
+
end
|
11
|
+
|
12
|
+
def rows
|
13
|
+
@rows ||=
|
14
|
+
begin
|
15
|
+
json_facet_response = @search.json_facet_response[@field.name.to_s]
|
16
|
+
data = json_facet_response.nil? ? [] : json_facet_response['buckets']
|
17
|
+
rows = []
|
18
|
+
data.each do |d|
|
19
|
+
rows << JsonFacetRow.new(d, self)
|
20
|
+
end
|
21
|
+
|
22
|
+
if @options[:sort] == :count
|
23
|
+
rows.sort! { |lrow, rrow| rrow.count <=> lrow.count }
|
24
|
+
else
|
25
|
+
rows.sort! { |lrow, rrow| lrow.value <=> rrow.value }
|
26
|
+
end
|
27
|
+
rows
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Search
|
3
|
+
class JsonFacetRow
|
4
|
+
attr_reader :value, :count, :nested
|
5
|
+
attr_writer :instance #:nodoc:
|
6
|
+
|
7
|
+
def initialize(data, facet) #:nodoc:
|
8
|
+
@value = data['val']
|
9
|
+
@count = data['distinct'] || data['count']
|
10
|
+
@facet = facet
|
11
|
+
@nested_key = data.keys.select { |k| data[k].is_a?(Hash) }.first
|
12
|
+
@nested = recursive_nested_initialization(data) unless @nested_key.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Return the instance referenced by this facet row. Only valid for field
|
17
|
+
# facets whose fields are defined with the :references key.
|
18
|
+
#
|
19
|
+
def instance
|
20
|
+
if !defined?(@instance)
|
21
|
+
@facet.populate_instances
|
22
|
+
end
|
23
|
+
@instance
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect
|
27
|
+
"<Sunspot::Search::FacetRow:#{value.inspect} (#{count}) #{nested.nil? ? '' : " nested_count=#{nested.size}"}>"
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def recursive_nested_initialization(data)
|
33
|
+
data[@nested_key]['buckets'].map do |d|
|
34
|
+
JsonFacetRow.new(d, @facet)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Search
|
3
|
+
class JsonFacetStats
|
4
|
+
def initialize(field, search, options)
|
5
|
+
@field, @search, @options = field, search, options
|
6
|
+
end
|
7
|
+
|
8
|
+
def rows
|
9
|
+
@rows ||=
|
10
|
+
begin
|
11
|
+
json_facet_response = @search.json_facet_response[@field.to_s]
|
12
|
+
data = json_facet_response.nil? ? [] : json_facet_response['buckets']
|
13
|
+
rows = []
|
14
|
+
data.each do |d|
|
15
|
+
rows << StatsJsonRow.new(d, nil, d['val'])
|
16
|
+
end
|
17
|
+
rows
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Search
|
3
|
+
class StatsJsonRow
|
4
|
+
attr_reader :data, :value, :nested
|
5
|
+
attr_writer :instance #:nodoc:
|
6
|
+
|
7
|
+
def initialize(data, facet = nil, value = nil) #:nodoc:
|
8
|
+
@data, @facet, @value = data, facet, value
|
9
|
+
@facet_fields = []
|
10
|
+
@nested_key = data.keys.select { |k| data[k].is_a?(Hash) }.first
|
11
|
+
@nested = recursive_nested_initialization(data) unless @nested_key.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
def min
|
15
|
+
data['min']
|
16
|
+
end
|
17
|
+
|
18
|
+
def max
|
19
|
+
data['max']
|
20
|
+
end
|
21
|
+
|
22
|
+
def count
|
23
|
+
data['count']
|
24
|
+
end
|
25
|
+
|
26
|
+
def sum
|
27
|
+
data['sum']
|
28
|
+
end
|
29
|
+
|
30
|
+
def missing
|
31
|
+
data['missing']
|
32
|
+
end
|
33
|
+
|
34
|
+
def sum_of_squares
|
35
|
+
data['sumsq']
|
36
|
+
end
|
37
|
+
alias :sumsq :sum_of_squares
|
38
|
+
|
39
|
+
def mean
|
40
|
+
data['avg']
|
41
|
+
end
|
42
|
+
alias :avg :mean
|
43
|
+
|
44
|
+
def standard_deviation
|
45
|
+
data['stddev']
|
46
|
+
end
|
47
|
+
|
48
|
+
def facet name
|
49
|
+
facets.find { |facet| facet.field.name == name.to_sym }
|
50
|
+
end
|
51
|
+
|
52
|
+
def facets
|
53
|
+
@facets ||= @facet_fields.map do |field|
|
54
|
+
StatsFacet.new(field, data['facets'][field.indexed_name])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def instance
|
59
|
+
if !defined?(@instance)
|
60
|
+
@facet.populate_instances
|
61
|
+
end
|
62
|
+
@instance
|
63
|
+
end
|
64
|
+
|
65
|
+
def inspect
|
66
|
+
"<Sunspot::Search::StatsJsonRow:#{value.inspect} min=#{min} max=#{max}"\
|
67
|
+
" count=#{count} sum=#{sum} missing=#{missing} sum_of_squares=#{sum_of_squares}"\
|
68
|
+
" mean=#{mean} standard_deviation=#{standard_deviation}"\
|
69
|
+
" #{nested.nil? ? '' : "nested_count=#{nested.size}"}>"
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def recursive_nested_initialization(data)
|
75
|
+
data[@nested_key]['buckets'].map do |d|
|
76
|
+
StatsJsonRow.new(d, @facet, d['val'])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -59,7 +59,9 @@ module Sunspot
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def inspect
|
62
|
-
"<Sunspot::Search::StatsRow:#{value.inspect} min=#{min} max=#{max}
|
62
|
+
"<Sunspot::Search::StatsRow:#{value.inspect} min=#{min} max=#{max}"\
|
63
|
+
" count=#{self.count} sum=#{sum} missing=#{missing} sum_of_squares=#{sum_of_squares}"\
|
64
|
+
" mean=#{mean} standard_deviation=#{standard_deviation}>"
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|
data/lib/sunspot/session.rb
CHANGED
@@ -254,11 +254,13 @@ module Sunspot
|
|
254
254
|
# RSolr::Connection::Base:: The connection for this session
|
255
255
|
#
|
256
256
|
def connection
|
257
|
-
@connection ||=
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
257
|
+
@connection ||= self.class.connection_class.connect(
|
258
|
+
url: config.solr.url,
|
259
|
+
read_timeout: config.solr.read_timeout,
|
260
|
+
open_timeout: config.solr.open_timeout,
|
261
|
+
proxy: config.solr.proxy,
|
262
|
+
update_format: config.solr.update_format || :xml
|
263
|
+
)
|
262
264
|
end
|
263
265
|
|
264
266
|
def indexer
|
data/lib/sunspot/util.rb
CHANGED
@@ -188,6 +188,29 @@ module Sunspot
|
|
188
188
|
RSolr.solr_escape(value).gsub(/([\s\.])/, '\\\\\1')
|
189
189
|
end
|
190
190
|
|
191
|
+
def parse_json_facet(field_name, options, setup)
|
192
|
+
field = setup.field(field_name)
|
193
|
+
if options[:time_range]
|
194
|
+
unless field.type.is_a?(Sunspot::Type::TimeType)
|
195
|
+
raise(
|
196
|
+
ArgumentError,
|
197
|
+
':time_range can only be specified for Date or Time fields'
|
198
|
+
)
|
199
|
+
end
|
200
|
+
Sunspot::Query::DateFieldJsonFacet.new(field, options, setup)
|
201
|
+
elsif options[:range]
|
202
|
+
unless [Sunspot::Type::TimeType, Sunspot::Type::FloatType, Sunspot::Type::IntegerType ].find{|type| field.type.is_a?(type)}
|
203
|
+
raise(
|
204
|
+
ArgumentError,
|
205
|
+
':range can only be specified for date or numeric fields'
|
206
|
+
)
|
207
|
+
end
|
208
|
+
Sunspot::Query::RangeJsonFacet.new(field, options, setup)
|
209
|
+
else
|
210
|
+
Sunspot::Query::FieldJsonFacet.new(field, options, setup)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
191
214
|
private
|
192
215
|
|
193
216
|
#
|
data/lib/sunspot/version.rb
CHANGED
@@ -66,7 +66,9 @@ shared_examples_for 'fulltext query' do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'puts default dismax parameters in subquery' do
|
69
|
-
expect(subqueries(:q).last[:qf].split(' ').sort).to
|
69
|
+
expect(subqueries(:q).last[:qf].split(' ').sort).to(
|
70
|
+
eq(%w(backwards_title_text body_textsv tags_textv text_array_text title_text))
|
71
|
+
)
|
70
72
|
end
|
71
73
|
|
72
74
|
it 'puts field list in main query' do
|
@@ -78,14 +80,18 @@ shared_examples_for 'fulltext query' do
|
|
78
80
|
search = search do
|
79
81
|
keywords 'keyword search'
|
80
82
|
end
|
81
|
-
expect(connection.searches.last[:qf].split(' ').sort).to
|
83
|
+
expect(connection.searches.last[:qf].split(' ').sort).to(
|
84
|
+
eq(%w(backwards_title_text body_textsv tags_textv text_array_text title_text))
|
85
|
+
)
|
82
86
|
end
|
83
87
|
|
84
88
|
it 'searches both stored and unstored text fields' do
|
85
89
|
search Post, Namespaced::Comment do
|
86
90
|
keywords 'keyword search'
|
87
91
|
end
|
88
|
-
expect(connection.searches.last[:qf].split(' ').sort).to
|
92
|
+
expect(connection.searches.last[:qf].split(' ').sort).to(
|
93
|
+
eq(%w(author_name_text backwards_title_text body_text body_textsv tags_textv text_array_text title_text))
|
94
|
+
)
|
89
95
|
end
|
90
96
|
|
91
97
|
it 'searches only specified text fields when specified' do
|
@@ -101,7 +107,7 @@ shared_examples_for 'fulltext query' do
|
|
101
107
|
exclude_fields :backwards_title, :body_mlt
|
102
108
|
end
|
103
109
|
end
|
104
|
-
expect(connection.searches.last[:qf].split(' ').sort).to eq(%w(body_textsv tags_textv title_text))
|
110
|
+
expect(connection.searches.last[:qf].split(' ').sort).to eq(%w(body_textsv tags_textv text_array_text title_text))
|
105
111
|
end
|
106
112
|
|
107
113
|
it 'assigns boost to fields when specified' do
|
@@ -173,7 +179,9 @@ shared_examples_for 'fulltext query' do
|
|
173
179
|
boost_fields :title => 1.5
|
174
180
|
end
|
175
181
|
end
|
176
|
-
expect(connection.searches.last[:qf].split(' ').sort).to
|
182
|
+
expect(connection.searches.last[:qf].split(' ').sort).to(
|
183
|
+
eq(%w(backwards_title_text body_textsv tags_textv text_array_text title_text^1.5))
|
184
|
+
)
|
177
185
|
end
|
178
186
|
|
179
187
|
it 'ignores boost fields that do not apply' do
|
@@ -182,7 +190,9 @@ shared_examples_for 'fulltext query' do
|
|
182
190
|
boost_fields :bogus => 1.2, :title => 1.5
|
183
191
|
end
|
184
192
|
end
|
185
|
-
expect(connection.searches.last[:qf].split(' ').sort).to
|
193
|
+
expect(connection.searches.last[:qf].split(' ').sort).to(
|
194
|
+
eq(%w(backwards_title_text body_textsv tags_textv text_array_text title_text^1.5))
|
195
|
+
)
|
186
196
|
end
|
187
197
|
|
188
198
|
it 'sets default boost with default fields' do
|
@@ -2,6 +2,7 @@ module IntegrationHelper
|
|
2
2
|
def self.included(base)
|
3
3
|
base.before(:all) do
|
4
4
|
Sunspot.config.solr.url = ENV['SOLR_URL'] || 'http://localhost:8983/solr/default'
|
5
|
+
Sunspot.config.solr.update_format = ENV['UPDATE_FORMAT'].to_sym if ENV['UPDATE_FORMAT']
|
5
6
|
Sunspot.reset!(true)
|
6
7
|
end
|
7
8
|
end
|
@@ -156,6 +156,136 @@ describe 'search faceting' do
|
|
156
156
|
end
|
157
157
|
end
|
158
158
|
|
159
|
+
context 'json facet options' do
|
160
|
+
before :all do
|
161
|
+
Sunspot.remove_all
|
162
|
+
facet_values = %w(zero one two three four)
|
163
|
+
facet_values.each_with_index do |value, i|
|
164
|
+
i.times { Sunspot.index(Post.new(:title => value, :blog_id => 1)) }
|
165
|
+
end
|
166
|
+
Sunspot.index(Post.new(:blog_id => 1))
|
167
|
+
Sunspot.index(Post.new(:title => 'zero', :blog_id => 2))
|
168
|
+
Sunspot.commit
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should return indexed elements' do
|
172
|
+
search = Sunspot.search(Post) do
|
173
|
+
json_facet(:title)
|
174
|
+
end
|
175
|
+
expect(search.facet(:title).rows.size).to eq(5)
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should limit the number of facet rows' do
|
179
|
+
search = Sunspot.search(Post) do
|
180
|
+
json_facet :title, :limit => 3
|
181
|
+
end
|
182
|
+
expect(search.facet(:title).rows.size).to eq(3)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'should not return zeros by default' do
|
186
|
+
search = Sunspot.search(Post) do
|
187
|
+
with :blog_id, 1
|
188
|
+
json_facet :title
|
189
|
+
end
|
190
|
+
expect(search.facet(:title).rows.map { |row| row.value }).not_to include('zero')
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should return a specified minimum count' do
|
194
|
+
search = Sunspot.search(Post) do
|
195
|
+
with :blog_id, 1
|
196
|
+
json_facet :title, :minimum_count => 2
|
197
|
+
end
|
198
|
+
expect(search.facet(:title).rows.map { |row| row.value }).to eq(%w(four three two))
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should order facets lexically' do
|
202
|
+
search = Sunspot.search(Post) do
|
203
|
+
with :blog_id, 1
|
204
|
+
json_facet :title, :sort => :index
|
205
|
+
end
|
206
|
+
expect(search.facet(:title).rows.map { |row| row.value }).to eq(%w(four one three two))
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'should order facets by count' do
|
210
|
+
search = Sunspot.search(Post) do
|
211
|
+
with :blog_id, 1
|
212
|
+
json_facet :title, :sort => :count
|
213
|
+
end
|
214
|
+
expect(search.facet(:title).rows.map { |row| row.value }).to eq(%w(four three two one))
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should limit facet values by prefix' do
|
218
|
+
search = Sunspot.search(Post) do
|
219
|
+
with :blog_id, 1
|
220
|
+
json_facet :title, :prefix => 't'
|
221
|
+
end
|
222
|
+
expect(search.facet(:title).rows.map { |row| row.value }.sort).to eq(%w(three two))
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
context 'nested json facet' do
|
228
|
+
before :all do
|
229
|
+
Sunspot.remove_all
|
230
|
+
facet_values = %w(zero one two three four)
|
231
|
+
nested_facet_values = %w(alfa bravo charlie delta)
|
232
|
+
|
233
|
+
facet_values.each do |value|
|
234
|
+
nested_facet_values.each do |v2|
|
235
|
+
Sunspot.index(Post.new(:title => value, :author_name => v2, :blog_id => 1))
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
0.upto(9) { |i| Sunspot.index(Post.new(:title => 'zero', :author_name => "another#{i}", :blog_id => 1)) }
|
240
|
+
|
241
|
+
Sunspot.commit
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should get nested' do
|
245
|
+
search = Sunspot.search(Post) do
|
246
|
+
json_facet(:title, nested: { field: :author_name } )
|
247
|
+
end
|
248
|
+
expect(search.facet(:title).rows.first.nested.size).to eq(4)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'without limit take the first 10' do
|
252
|
+
search = Sunspot.search(Post) do
|
253
|
+
json_facet(:title, nested: { field: :author_name } )
|
254
|
+
end
|
255
|
+
expect(search.facet(:title).rows.last.nested.size).to eq(10)
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'without limit' do
|
259
|
+
search = Sunspot.search(Post) do
|
260
|
+
json_facet(:title, nested: { field: :author_name, limit: -1 } )
|
261
|
+
end
|
262
|
+
expect(search.facet(:title).rows.last.nested.size).to eq(14)
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'works with distinct' do
|
266
|
+
search = Sunspot.search(Post) do
|
267
|
+
json_facet(:title, nested: { field: :author_name, distinct: { strategy: :unique } } )
|
268
|
+
end
|
269
|
+
expect(search.facet(:title).rows.first.nested.map(&:count).uniq.size).to eq(1)
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'should limit the nested facet' do
|
273
|
+
search = Sunspot.search(Post) do
|
274
|
+
json_facet(:title, nested: { field: :author_name, limit: 2 } )
|
275
|
+
end
|
276
|
+
expect(search.facet(:title).rows.first.nested.size).to eq(2)
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'should work nested of nested' do
|
280
|
+
search = Sunspot.search(Post) do
|
281
|
+
json_facet(:title, nested: { field: :author_name, nested: { field: :title } } )
|
282
|
+
end
|
283
|
+
expect(search.facet(:title).rows.first.nested.first.nested.size).to eq(1)
|
284
|
+
expect(search.facet(:title).rows.first.nested.first.nested.first.nested).to eq(nil)
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
159
289
|
context 'prefix escaping' do
|
160
290
|
before do
|
161
291
|
Sunspot.remove_all
|
@@ -259,6 +389,57 @@ describe 'search faceting' do
|
|
259
389
|
end
|
260
390
|
end
|
261
391
|
|
392
|
+
context 'distinct field facets' do
|
393
|
+
before :all do
|
394
|
+
Sunspot.remove_all
|
395
|
+
|
396
|
+
Sunspot.index!(
|
397
|
+
(0..5).map { |i| Post.new(:blog_id => i, :title => 'title') }
|
398
|
+
)
|
399
|
+
|
400
|
+
0.upto(3) { |i| Sunspot.index(Post.new(:blog_id => i, :title => 'title')) }
|
401
|
+
|
402
|
+
Sunspot.index!(Post.new(:blog_id => 4, :title => 'other title'))
|
403
|
+
Sunspot.index!(Post.new(:blog_id => 5, :title => 'other title'))
|
404
|
+
|
405
|
+
Sunspot.index!(Post.new(:blog_id => 40, :title => 'title'))
|
406
|
+
Sunspot.index!(Post.new(:blog_id => 40, :title => 'title'))
|
407
|
+
|
408
|
+
Sunspot.index!(Post.new(:blog_id => 40, :title => 'other title'))
|
409
|
+
Sunspot.index!(Post.new(:blog_id => 40, :title => 'other title'))
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'should return unique indexed elements for a field' do
|
413
|
+
search = Sunspot.search(Post) do
|
414
|
+
json_facet(:blog_id, distinct: { strategy: :unique })
|
415
|
+
end
|
416
|
+
|
417
|
+
expect(search.facet(:blog_id).rows.size).to eq(7)
|
418
|
+
expect(search.facet(:blog_id).rows.map(&:count).uniq.size).to eq(1)
|
419
|
+
end
|
420
|
+
|
421
|
+
it 'should return unique indexed elements for a field and facet on a field' do
|
422
|
+
search = Sunspot.search(Post) do
|
423
|
+
json_facet(:blog_id, distinct: { group_by: :title, strategy: :unique })
|
424
|
+
end
|
425
|
+
|
426
|
+
expect(search.facet(:blog_id).rows.size).to eq(2)
|
427
|
+
expect(search.facet(:blog_id).rows[0].count).to eq(3)
|
428
|
+
expect(search.facet(:blog_id).rows[1].count).to eq(7)
|
429
|
+
end
|
430
|
+
|
431
|
+
it 'should return unique indexed elements for a field and facet on a field with hll' do
|
432
|
+
search = Sunspot.search(Post) do
|
433
|
+
json_facet(:blog_id, distinct: { group_by: :title, strategy: :hll })
|
434
|
+
end
|
435
|
+
|
436
|
+
expect(search.facet(:blog_id).rows.size).to eq(2)
|
437
|
+
expect(search.facet(:blog_id).rows[0].count).to eq(3)
|
438
|
+
expect(search.facet(:blog_id).rows[1].count).to eq(7)
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
442
|
+
|
262
443
|
context 'date facets' do
|
263
444
|
before :all do
|
264
445
|
Sunspot.remove_all
|
@@ -278,6 +459,38 @@ describe 'search faceting' do
|
|
278
459
|
expect(search.facet(:published_at).rows.last.value).to eq((time + 60*60*24)..(time + 60*60*24*2))
|
279
460
|
expect(search.facet(:published_at).rows.last.count).to eq(1)
|
280
461
|
end
|
462
|
+
|
463
|
+
it 'json facet should return time ranges' do
|
464
|
+
days_diff = 15
|
465
|
+
time_from = Time.utc(2009, 7, 8)
|
466
|
+
time_to = Time.utc(2009, 7, 8 + days_diff)
|
467
|
+
search = Sunspot.search(Post) do
|
468
|
+
json_facet(
|
469
|
+
:published_at,
|
470
|
+
:time_range => time_from..time_to
|
471
|
+
)
|
472
|
+
end
|
473
|
+
|
474
|
+
expect(search.facet(:published_at).rows.size).to eq(days_diff)
|
475
|
+
expect(search.facet(:published_at).rows[0].count).to eq(2)
|
476
|
+
expect(search.facet(:published_at).rows[1].count).to eq(1)
|
477
|
+
end
|
478
|
+
|
479
|
+
it 'json facet should return time ranges with custom gap' do
|
480
|
+
days_diff = 10
|
481
|
+
time_from = Time.utc(2009, 7, 8)
|
482
|
+
time_to = Time.utc(2009, 7, 8 + days_diff)
|
483
|
+
search = Sunspot.search(Post) do
|
484
|
+
json_facet(
|
485
|
+
:published_at,
|
486
|
+
:time_range => time_from..time_to,
|
487
|
+
gap: 60*60*24*2
|
488
|
+
)
|
489
|
+
end
|
490
|
+
expect(search.facet(:published_at).rows.size).to eq(days_diff / 2)
|
491
|
+
expect(search.facet(:published_at).rows[0].count).to eq(3)
|
492
|
+
end
|
493
|
+
|
281
494
|
end
|
282
495
|
|
283
496
|
context 'class facets' do
|
@@ -332,7 +332,7 @@ describe 'scoped_search' do
|
|
332
332
|
expect(Sunspot.search(Post) do
|
333
333
|
without(:blog_id, [])
|
334
334
|
end.results).to eq(posts)
|
335
|
-
end
|
335
|
+
end
|
336
336
|
|
337
337
|
it 'should return results, ignoring any restriction in a conjunction that has been passed an empty array' do
|
338
338
|
posts = (1..3).map { |i| Post.new(:blog_id => i)}
|
@@ -3,9 +3,9 @@ require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
|
3
3
|
describe 'search stats' do
|
4
4
|
before :each do
|
5
5
|
Sunspot.remove_all
|
6
|
-
@posts = Post.new(:ratings_average => 4.0, :blog_id => 2),
|
7
|
-
Post.new(:ratings_average => 4.0, :blog_id => 1),
|
8
|
-
Post.new(:ratings_average => 3.0, :blog_id => 2)
|
6
|
+
@posts = Post.new(:ratings_average => 4.0, :author_name => 'plinio', :blog_id => 2),
|
7
|
+
Post.new(:ratings_average => 4.0, :author_name => 'caio', :blog_id => 1),
|
8
|
+
Post.new(:ratings_average => 3.0, :author_name => 'sempronio', :blog_id => 2)
|
9
9
|
Sunspot.index!(@posts)
|
10
10
|
end
|
11
11
|
|
@@ -44,4 +44,45 @@ describe 'search stats' do
|
|
44
44
|
end.stats(:average_rating).facet(:blog_id).rows[1].max).to eq(4.0)
|
45
45
|
end
|
46
46
|
end
|
47
|
+
|
48
|
+
describe 'json facets' do
|
49
|
+
it 'returns minimum on facet row with two blog ids' do
|
50
|
+
expect(Sunspot.search(Post) do
|
51
|
+
stats :average_rating, sort: :min do
|
52
|
+
json_facet :blog_id
|
53
|
+
end
|
54
|
+
end.json_facet_stats(:blog_id).rows[1].min).to eq(3.0)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns maximum on facet row with two blog ids' do
|
58
|
+
expect(Sunspot.search(Post) do
|
59
|
+
stats :average_rating, sort: :max do
|
60
|
+
json_facet :blog_id
|
61
|
+
end
|
62
|
+
end.json_facet_stats(:blog_id).rows[1].max).to eq(4.0)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns only sum' do
|
66
|
+
search = Sunspot.search(Post) do
|
67
|
+
stats :average_rating, stats: [:sum] do
|
68
|
+
json_facet :blog_id
|
69
|
+
end
|
70
|
+
end
|
71
|
+
expect(search.json_facet_stats(:blog_id).rows[1].max).to eq(nil)
|
72
|
+
expect(search.json_facet_stats(:blog_id).rows[1].min).to eq(nil)
|
73
|
+
expect(search.json_facet_stats(:blog_id).rows[1].avg).to eq(nil)
|
74
|
+
expect(search.json_facet_stats(:blog_id).rows[1].sumsq).to eq(nil)
|
75
|
+
expect(search.json_facet_stats(:blog_id).rows[1].sum).to eq(4.0)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'works with nested facets' do
|
79
|
+
search = Sunspot.search(Post) do
|
80
|
+
stats :average_rating, sort: :min do
|
81
|
+
json_facet(:blog_id, nested: { field: :author_name, limit: 3, nested: { field: :average_rating } } )
|
82
|
+
end
|
83
|
+
end
|
84
|
+
expect(search.json_facet_stats(:blog_id).rows[1].nested.first.nested.first.min).to eq(4.0)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
47
88
|
end
|
data/spec/mocks/post.rb
CHANGED
@@ -37,12 +37,16 @@ end
|
|
37
37
|
|
38
38
|
Sunspot.setup(Post) do
|
39
39
|
text :title, :boost => 2
|
40
|
+
text :text_array, :boost => 3 do
|
41
|
+
[title, title]
|
42
|
+
end
|
40
43
|
text :body, :stored => true, :more_like_this => true
|
41
44
|
text :backwards_title do
|
42
45
|
title.reverse if title
|
43
46
|
end
|
44
47
|
text :tags, :more_like_this => true
|
45
48
|
string :title, :stored => true
|
49
|
+
string :author_name
|
46
50
|
integer :blog_id, :references => Blog
|
47
51
|
integer :category_ids, :multiple => true
|
48
52
|
float :average_rating, :using => :ratings_average, :trie => true
|
data/spec/spec_helper.rb
CHANGED
@@ -23,14 +23,10 @@ RSpec.configure do |config|
|
|
23
23
|
config.order = 'random'
|
24
24
|
|
25
25
|
# Mock session available to all spec/api tests
|
26
|
-
config.include MockSessionHelper,
|
27
|
-
:type => :api,
|
28
|
-
:file_path => /spec[\\\/]api/
|
26
|
+
config.include MockSessionHelper, type: :api, file_path: /spec[\\\/]api/
|
29
27
|
|
30
28
|
# Real Solr instance is available to integration tests
|
31
|
-
config.include IntegrationHelper,
|
32
|
-
:type => :integration,
|
33
|
-
:file_path => /spec[\\\/]integration/
|
29
|
+
config.include IntegrationHelper, type: :integration, file_path: /spec[\\\/]integration/
|
34
30
|
|
35
31
|
# Nested under spec/api
|
36
32
|
[:indexer, :query, :search].each do |spec_type|
|
data/sunspot.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.add_dependency 'pr_geohash', '~>1.0'
|
32
32
|
|
33
33
|
s.add_development_dependency 'rake', '< 12.3'
|
34
|
-
s.add_development_dependency 'rspec'
|
34
|
+
s.add_development_dependency 'rspec', '~> 3.7'
|
35
35
|
s.add_development_dependency 'appraisal', '2.2.0'
|
36
36
|
|
37
37
|
s.rdoc_options << '--webcvs=http://github.com/outoftime/sunspot/tree/master/%s' <<
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sunspot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Brown
|
@@ -30,7 +30,7 @@ authors:
|
|
30
30
|
autorequire:
|
31
31
|
bindir: bin
|
32
32
|
cert_chain: []
|
33
|
-
date: 2018-
|
33
|
+
date: 2018-04-08 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: rsolr
|
@@ -84,16 +84,16 @@ dependencies:
|
|
84
84
|
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '3.7'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '3.7'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: appraisal
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,14 +159,17 @@ files:
|
|
159
159
|
- lib/sunspot/query.rb
|
160
160
|
- lib/sunspot/query/abstract_field_facet.rb
|
161
161
|
- lib/sunspot/query/abstract_fulltext.rb
|
162
|
+
- lib/sunspot/query/abstract_json_field_facet.rb
|
162
163
|
- lib/sunspot/query/bbox.rb
|
163
164
|
- lib/sunspot/query/boost_query.rb
|
164
165
|
- lib/sunspot/query/common_query.rb
|
165
166
|
- lib/sunspot/query/composite_fulltext.rb
|
166
167
|
- lib/sunspot/query/connective.rb
|
167
168
|
- lib/sunspot/query/date_field_facet.rb
|
169
|
+
- lib/sunspot/query/date_field_json_facet.rb
|
168
170
|
- lib/sunspot/query/dismax.rb
|
169
171
|
- lib/sunspot/query/field_facet.rb
|
172
|
+
- lib/sunspot/query/field_json_facet.rb
|
170
173
|
- lib/sunspot/query/field_list.rb
|
171
174
|
- lib/sunspot/query/field_stats.rb
|
172
175
|
- lib/sunspot/query/filter.rb
|
@@ -182,6 +185,7 @@ files:
|
|
182
185
|
- lib/sunspot/query/pagination.rb
|
183
186
|
- lib/sunspot/query/query_facet.rb
|
184
187
|
- lib/sunspot/query/range_facet.rb
|
188
|
+
- lib/sunspot/query/range_json_facet.rb
|
185
189
|
- lib/sunspot/query/restriction.rb
|
186
190
|
- lib/sunspot/query/scope.rb
|
187
191
|
- lib/sunspot/query/sort.rb
|
@@ -197,11 +201,14 @@ files:
|
|
197
201
|
- lib/sunspot/search/facet_row.rb
|
198
202
|
- lib/sunspot/search/field_facet.rb
|
199
203
|
- lib/sunspot/search/field_group.rb
|
204
|
+
- lib/sunspot/search/field_json_facet.rb
|
200
205
|
- lib/sunspot/search/field_stats.rb
|
201
206
|
- lib/sunspot/search/group.rb
|
202
207
|
- lib/sunspot/search/highlight.rb
|
203
208
|
- lib/sunspot/search/hit.rb
|
204
209
|
- lib/sunspot/search/hit_enumerable.rb
|
210
|
+
- lib/sunspot/search/json_facet_row.rb
|
211
|
+
- lib/sunspot/search/json_facet_stats.rb
|
205
212
|
- lib/sunspot/search/more_like_this_search.rb
|
206
213
|
- lib/sunspot/search/paginated_collection.rb
|
207
214
|
- lib/sunspot/search/query_facet.rb
|
@@ -209,6 +216,7 @@ files:
|
|
209
216
|
- lib/sunspot/search/range_facet.rb
|
210
217
|
- lib/sunspot/search/standard_search.rb
|
211
218
|
- lib/sunspot/search/stats_facet.rb
|
219
|
+
- lib/sunspot/search/stats_json_row.rb
|
212
220
|
- lib/sunspot/search/stats_row.rb
|
213
221
|
- lib/sunspot/session.rb
|
214
222
|
- lib/sunspot/session_proxy.rb
|
@@ -348,7 +356,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
348
356
|
version: '0'
|
349
357
|
requirements: []
|
350
358
|
rubyforge_project: sunspot
|
351
|
-
rubygems_version: 2.6
|
359
|
+
rubygems_version: 2.7.6
|
352
360
|
signing_key:
|
353
361
|
specification_version: 4
|
354
362
|
summary: Library for expressive, powerful interaction with the Solr search engine
|