sunspot 2.1.0 → 2.1.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.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/History.txt +10 -0
- data/lib/sunspot.rb +6 -6
- data/lib/sunspot/batcher.rb +1 -1
- data/lib/sunspot/dsl.rb +1 -1
- data/lib/sunspot/dsl/field_query.rb +47 -7
- data/lib/sunspot/dsl/field_stats.rb +18 -0
- data/lib/sunspot/dsl/fields.rb +10 -1
- data/lib/sunspot/field.rb +15 -0
- data/lib/sunspot/field_factory.rb +33 -0
- data/lib/sunspot/indexer.rb +1 -0
- data/lib/sunspot/query.rb +1 -1
- data/lib/sunspot/query/common_query.rb +5 -0
- data/lib/sunspot/query/field_stats.rb +28 -0
- data/lib/sunspot/query/geofilt.rb +8 -3
- data/lib/sunspot/query/restriction.rb +5 -2
- data/lib/sunspot/query/sort.rb +35 -0
- data/lib/sunspot/search.rb +2 -1
- data/lib/sunspot/search/abstract_search.rb +57 -35
- data/lib/sunspot/search/field_facet.rb +4 -4
- data/lib/sunspot/search/field_stats.rb +21 -0
- data/lib/sunspot/search/stats_facet.rb +25 -0
- data/lib/sunspot/search/stats_row.rb +66 -0
- data/lib/sunspot/session.rb +6 -6
- data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +6 -4
- data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +16 -8
- data/lib/sunspot/setup.rb +6 -0
- data/lib/sunspot/version.rb +1 -1
- data/spec/api/class_set_spec.rb +3 -3
- data/spec/api/indexer/fixed_fields_spec.rb +5 -0
- data/spec/api/indexer/removal_spec.rb +13 -3
- data/spec/api/query/faceting_examples.rb +19 -0
- data/spec/api/query/join_spec.rb +19 -0
- data/spec/api/query/standard_spec.rb +1 -0
- data/spec/api/query/stats_examples.rb +66 -0
- data/spec/api/search/paginated_collection_spec.rb +1 -1
- data/spec/api/search/stats_spec.rb +94 -0
- data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +8 -2
- data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +14 -2
- data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +3 -3
- data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +1 -1
- data/spec/helpers/search_helper.rb +30 -0
- data/spec/integration/highlighting_spec.rb +3 -3
- data/spec/integration/indexing_spec.rb +3 -2
- data/spec/integration/scoped_search_spec.rb +30 -0
- data/spec/integration/stats_spec.rb +47 -0
- data/spec/mocks/photo.rb +14 -1
- data/sunspot.gemspec +1 -2
- data/tasks/rdoc.rake +22 -14
- metadata +32 -41
@@ -45,23 +45,31 @@ module Sunspot
|
|
45
45
|
#
|
46
46
|
# See Sunspot.remove_by_id
|
47
47
|
#
|
48
|
-
def remove_by_id(clazz,
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
def remove_by_id(clazz, *ids)
|
49
|
+
ids.flatten!
|
50
|
+
ids_by_session(clazz, ids).each do |session, ids|
|
51
|
+
session.remove_by_id(clazz, ids)
|
52
|
+
end
|
52
53
|
end
|
53
54
|
|
54
55
|
#
|
55
56
|
# See Sunspot.remove_by_id!
|
56
57
|
#
|
57
|
-
def remove_by_id!(clazz,
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
def remove_by_id!(clazz, *ids)
|
59
|
+
ids.flatten!
|
60
|
+
ids_by_session(clazz, ids).each do |session, ids|
|
61
|
+
session.remove_by_id!(clazz, ids)
|
62
|
+
end
|
61
63
|
end
|
62
64
|
|
63
65
|
private
|
64
66
|
|
67
|
+
def ids_by_session(clazz, ids)
|
68
|
+
ids.group_by do |id|
|
69
|
+
session_for_index_id(Adapters::InstanceAdapter.index_id_for(clazz, id))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
65
73
|
def session_for_index_id(index_id)
|
66
74
|
@sessions[id_hash(index_id) % @sessions.length]
|
67
75
|
end
|
data/lib/sunspot/setup.rb
CHANGED
@@ -38,6 +38,12 @@ module Sunspot
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def add_join_field_factory(name, type, options = {}, &block)
|
42
|
+
field_factory = FieldFactory::Join.new(name, type, options, &block)
|
43
|
+
@field_factories[field_factory.signature] = field_factory
|
44
|
+
@field_factories_cache[field_factory.name] = field_factory
|
45
|
+
end
|
46
|
+
|
41
47
|
#
|
42
48
|
# Add field_factories for fulltext search
|
43
49
|
#
|
data/lib/sunspot/version.rb
CHANGED
data/spec/api/class_set_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Sunspot::ClassSet do
|
4
4
|
it "is enumerable" do
|
5
|
-
class1, class2 =
|
5
|
+
class1, class2 = double(:name => "Class1"), double(:name => "Class2")
|
6
6
|
|
7
7
|
set = described_class.new
|
8
8
|
set << class1 << class2
|
@@ -13,11 +13,11 @@ describe Sunspot::ClassSet do
|
|
13
13
|
it "replaces classes with the same name" do
|
14
14
|
set = described_class.new
|
15
15
|
|
16
|
-
class1 =
|
16
|
+
class1 = double(:name => "Class1")
|
17
17
|
set << class1
|
18
18
|
set.to_a.should == [class1]
|
19
19
|
|
20
|
-
class1_dup =
|
20
|
+
class1_dup = double(:name => "Class1")
|
21
21
|
set << class1_dup
|
22
22
|
set.to_a.should == [class1_dup]
|
23
23
|
end
|
@@ -11,6 +11,11 @@ describe 'indexing fixed fields', :type => :indexer do
|
|
11
11
|
connection.should have_add_with(:type => ['Post', 'SuperClass', 'MockRecord'])
|
12
12
|
end
|
13
13
|
|
14
|
+
it 'should not index join fields' do
|
15
|
+
session.index PhotoContainer.new
|
16
|
+
connection.should_not have_add_with(:photo_caption => 'blah')
|
17
|
+
end
|
18
|
+
|
14
19
|
it 'should index class name' do
|
15
20
|
session.index post
|
16
21
|
connection.should have_add_with(:class_name => 'Post')
|
@@ -11,10 +11,20 @@ describe 'document removal', :type => :indexer do
|
|
11
11
|
connection.should have_delete('Post 1')
|
12
12
|
end
|
13
13
|
|
14
|
-
it 'removes an object by type and
|
15
|
-
|
14
|
+
it 'removes an object by type and ids' do
|
15
|
+
session.remove_by_id(Post, 1, 2)
|
16
|
+
connection.should have_delete('Post 1', 'Post 2')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'removes an object by type and ids array' do
|
20
|
+
session.remove_by_id(Post, [1, 2])
|
21
|
+
connection.should have_delete('Post 1', 'Post 2')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'removes an object by type and ids and immediately commits' do
|
25
|
+
connection.should_receive(:delete_by_id).with(['Post 1', 'Post 2', 'Post 3']).ordered
|
16
26
|
connection.should_receive(:commit).ordered
|
17
|
-
session.remove_by_id!(Post, 1)
|
27
|
+
session.remove_by_id!(Post, 1, 2, 3)
|
18
28
|
end
|
19
29
|
|
20
30
|
it 'removes an object from the index and immediately commits' do
|
@@ -112,6 +112,25 @@ shared_examples_for "facetable query" do
|
|
112
112
|
end.should raise_error(ArgumentError)
|
113
113
|
end
|
114
114
|
|
115
|
+
it 'tags and excludes a geofilt in a field facet' do
|
116
|
+
search do
|
117
|
+
post_geo = with(:coordinates_new).in_radius(32, -68, 1)
|
118
|
+
facet(:coordinates_new, :exclude => post_geo) do
|
119
|
+
row(0..10) do
|
120
|
+
with(:coordinates_new).in_radius(32, -68, 10)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
if connection.searches.last.has_key?(:"mlt.fl")
|
125
|
+
filter_tag = get_filter_tag('_query_:"{!geofilt sfield=coordinates_new_ll pt=32,-68 d=1}"')
|
126
|
+
else
|
127
|
+
filter_tag = get_filter_tag('{!geofilt sfield=coordinates_new_ll pt=32,-68 d=1}')
|
128
|
+
end
|
129
|
+
connection.should have_last_search_with(
|
130
|
+
:"facet.query" => "{!ex=#{filter_tag}}_query_:\"{!geofilt sfield=coordinates_new_ll pt=32,-68 d=10}\""
|
131
|
+
)
|
132
|
+
end
|
133
|
+
|
115
134
|
it 'tags and excludes a scope filter in a field facet' do
|
116
135
|
search do
|
117
136
|
blog_filter = with(:blog_id, 1)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe 'join' do
|
4
|
+
it 'should search by join' do
|
5
|
+
session.search PhotoContainer do
|
6
|
+
with(:caption, 'blah')
|
7
|
+
end
|
8
|
+
connection.should have_last_search_including(
|
9
|
+
:fq, "{!join from=photo_container_id to=id}caption_s:blah")
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should greater_than search by join' do
|
13
|
+
session.search PhotoContainer do
|
14
|
+
with(:photo_rating).greater_than(3)
|
15
|
+
end
|
16
|
+
connection.should have_last_search_including(
|
17
|
+
:fq, "{!join from=photo_container_id to=id}average_rating_ft:{3\\.0 TO *}")
|
18
|
+
end
|
19
|
+
end
|
@@ -12,6 +12,7 @@ describe 'standard query', :type => :query do
|
|
12
12
|
it_should_behave_like "query with text field scoping"
|
13
13
|
it_should_behave_like "geohash query"
|
14
14
|
it_should_behave_like "spatial query"
|
15
|
+
it_should_behave_like "stats query"
|
15
16
|
|
16
17
|
it 'adds a no-op query to :q parameter when no :q provided' do
|
17
18
|
session.search Post do
|
@@ -0,0 +1,66 @@
|
|
1
|
+
shared_examples_for 'stats query' do
|
2
|
+
it 'does not use stats unless requested' do
|
3
|
+
search
|
4
|
+
connection.should_not have_last_search_with(:stats)
|
5
|
+
end
|
6
|
+
|
7
|
+
it 'uses stats when requested' do
|
8
|
+
search do
|
9
|
+
stats :average_rating
|
10
|
+
end
|
11
|
+
connection.should have_last_search_with(:stats => true)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'requests single field stats' do
|
15
|
+
search do
|
16
|
+
stats :average_rating
|
17
|
+
end
|
18
|
+
connection.should have_last_search_with(:"stats.field" => %w{average_rating_ft})
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'requests multiple field stats' do
|
22
|
+
search do
|
23
|
+
stats :average_rating, :published_at
|
24
|
+
end
|
25
|
+
connection.should have_last_search_with(:"stats.field" => %w{average_rating_ft published_at_dt})
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'facets on a stats field' do
|
29
|
+
search do
|
30
|
+
stats :average_rating do
|
31
|
+
facet :featured
|
32
|
+
end
|
33
|
+
end
|
34
|
+
connection.should have_last_search_with(:"f.average_rating_ft.stats.facet" => %w{featured_bs})
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'only facets on a stats field when requested' do
|
38
|
+
search do
|
39
|
+
stats :average_rating
|
40
|
+
end
|
41
|
+
connection.should_not have_last_search_with(:"f.average_rating_ft.stats.facet")
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'facets on multiple stats fields' do
|
45
|
+
search do
|
46
|
+
stats :average_rating, :published_at do
|
47
|
+
facet :featured
|
48
|
+
end
|
49
|
+
end
|
50
|
+
connection.should have_last_search_with(
|
51
|
+
:"f.average_rating_ft.stats.facet" => %w{featured_bs},
|
52
|
+
:"f.published_at_dt.stats.facet" => %w{featured_bs}
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'supports facets on stats field' do
|
57
|
+
search do
|
58
|
+
stats :average_rating do
|
59
|
+
facet :featured, :primary_category_id
|
60
|
+
end
|
61
|
+
end
|
62
|
+
connection.should have_last_search_with(
|
63
|
+
:"f.average_rating_ft.stats.facet" => %w{featured_bs primary_category_id_i}
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe 'stats', :type => :search do
|
4
|
+
it 'returns field name for stats field' do
|
5
|
+
stub_stats(:average_rating_ft, {})
|
6
|
+
result = session.search Post do
|
7
|
+
stats :average_rating
|
8
|
+
end
|
9
|
+
result.stats(:average_rating).field_name.should == :average_rating
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns min for stats field' do
|
13
|
+
stub_stats(:average_rating_ft, { 'min' => 1.0 })
|
14
|
+
result = session.search Post do
|
15
|
+
stats :average_rating
|
16
|
+
end
|
17
|
+
result.stats(:average_rating).min.should == 1.0
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns max for stats field' do
|
21
|
+
stub_stats(:average_rating_ft, { 'max' => 5.0 })
|
22
|
+
result = session.search Post do
|
23
|
+
stats :average_rating
|
24
|
+
end
|
25
|
+
result.stats(:average_rating).max.should == 5.0
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns count for stats field' do
|
29
|
+
stub_stats(:average_rating_ft, { 'count' => 120 })
|
30
|
+
result = session.search Post do
|
31
|
+
stats :average_rating
|
32
|
+
end
|
33
|
+
result.stats(:average_rating).count.should == 120
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns sum for stats field' do
|
37
|
+
stub_stats(:average_rating_ft, { 'sum' => 2200.0 })
|
38
|
+
result = session.search Post do
|
39
|
+
stats :average_rating
|
40
|
+
end
|
41
|
+
result.stats(:average_rating).sum.should == 2200.0
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns facet rows for stats field' do
|
45
|
+
stub_stats_facets(:average_rating_ft, 'featured_bs' => {
|
46
|
+
'false' => {},
|
47
|
+
'true' => {}
|
48
|
+
})
|
49
|
+
result = session.search Post do
|
50
|
+
stats :average_rating do
|
51
|
+
facet :featured
|
52
|
+
end
|
53
|
+
end
|
54
|
+
stats_facet_values(result, :average_rating, :featured).should == [false, true]
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns facet stats for stats field' do
|
58
|
+
stub_stats_facets(:average_rating_ft, 'featured_bs' => {
|
59
|
+
'true' => { 'min' => 2.0, 'max' => 4.0 }
|
60
|
+
})
|
61
|
+
result = session.search Post do
|
62
|
+
stats :average_rating do
|
63
|
+
facet :featured
|
64
|
+
end
|
65
|
+
end
|
66
|
+
stats_facet_stats(result, :average_rating, :featured, true).min.should == 2.0
|
67
|
+
stats_facet_stats(result, :average_rating, :featured, true).max.should == 4.0
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'returns instantiated stats facet values' do
|
71
|
+
blogs = 2.times.map { Blog.new }
|
72
|
+
stub_stats_facets(:average_rating_ft, 'blog_id_i' => {
|
73
|
+
blogs[0].id.to_s => {}, blogs[1].id.to_s => {} })
|
74
|
+
search = session.search(Post) do
|
75
|
+
stats :average_rating do
|
76
|
+
facet :blog_id
|
77
|
+
end
|
78
|
+
end
|
79
|
+
search.stats(:average_rating).facet(:blog_id).rows.map { |row| row.instance }.should == blogs
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'only returns verified instances when requested' do
|
83
|
+
blog = Blog.new
|
84
|
+
stub_stats_facets(:average_rating_ft, 'blog_id_i' => {
|
85
|
+
blog.id.to_s => {}, '0' => {} })
|
86
|
+
|
87
|
+
search = session.search(Post) do
|
88
|
+
stats :average_rating do
|
89
|
+
facet :blog_id
|
90
|
+
end
|
91
|
+
end
|
92
|
+
search.stats(:average_rating).facet(:blog_id).rows(:verified => true).map { |row| row.instance }.should == [blog]
|
93
|
+
end
|
94
|
+
end
|
@@ -18,11 +18,17 @@ describe Sunspot::SessionProxy::ClassShardingSessionProxy do
|
|
18
18
|
|
19
19
|
[:remove_by_id, :remove_by_id!].each do |method|
|
20
20
|
it "should delegate #{method} to appropriate shard" do
|
21
|
-
@proxy.post_session.should_receive(method).with(Post, 1)
|
22
|
-
@proxy.photo_session.should_receive(method).with(Photo, 1)
|
21
|
+
@proxy.post_session.should_receive(method).with(Post, [1])
|
22
|
+
@proxy.photo_session.should_receive(method).with(Photo, [1])
|
23
23
|
@proxy.send(method, Post, 1)
|
24
24
|
@proxy.send(method, Photo, 1)
|
25
25
|
end
|
26
|
+
it "should delegate #{method} to appropriate shard given ids" do
|
27
|
+
@proxy.post_session.should_receive(method).with(Post, [1, 2])
|
28
|
+
@proxy.photo_session.should_receive(method).with(Photo, [1, 2])
|
29
|
+
@proxy.send(method, Post, 1, 2)
|
30
|
+
@proxy.send(method, Photo, [1, 2])
|
31
|
+
end
|
26
32
|
end
|
27
33
|
|
28
34
|
[:remove_all, :remove_all!].each do |method|
|
@@ -19,10 +19,22 @@ describe Sunspot::SessionProxy::ShardingSessionProxy do
|
|
19
19
|
|
20
20
|
[:remove_by_id, :remove_by_id!].each do |method|
|
21
21
|
it "should delegate #{method} to appropriate session" do
|
22
|
-
@proxy.sessions[
|
23
|
-
@proxy.sessions[
|
22
|
+
@proxy.sessions[1].should_receive(method).with(Post, [3])
|
23
|
+
@proxy.sessions[0].should_receive(method).with(Post, [2])
|
24
|
+
@proxy.sessions[1].should_receive(method).with(Post, [1])
|
24
25
|
@proxy.send(method, Post, 1)
|
25
26
|
@proxy.send(method, Post, 2)
|
27
|
+
@proxy.send(method, Post, 3)
|
28
|
+
end
|
29
|
+
it "should delegate #{method} to appropriate session given splatted index ids" do
|
30
|
+
@proxy.sessions[0].should_receive(method).with(Post, [2])
|
31
|
+
@proxy.sessions[1].should_receive(method).with(Post, [1, 3])
|
32
|
+
@proxy.send(method, Post, 1, 2, 3)
|
33
|
+
end
|
34
|
+
it "should delegate #{method} to appropriate session given array of index ids" do
|
35
|
+
@proxy.sessions[0].should_receive(method).with(Post, [2])
|
36
|
+
@proxy.sessions[1].should_receive(method).with(Post, [1, 3])
|
37
|
+
@proxy.send(method, Post, [1, 2, 3])
|
26
38
|
end
|
27
39
|
end
|
28
40
|
|
@@ -33,14 +33,14 @@ describe Sunspot::SessionProxy::Retry5xxSessionProxy do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should behave normally without a stubbed exception" do
|
36
|
-
@sunspot_session.should_receive(:index).and_return(
|
36
|
+
@sunspot_session.should_receive(:index).and_return(double)
|
37
37
|
Sunspot.index(post)
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should be successful with a single exception followed by a sucess" do
|
41
41
|
e = FakeRSolrErrorHttp.new(fake_rsolr_request, fake_rsolr_response(503))
|
42
42
|
@sunspot_session.should_receive(:index).and_return do
|
43
|
-
@sunspot_session.should_receive(:index).and_return(
|
43
|
+
@sunspot_session.should_receive(:index).and_return(double)
|
44
44
|
raise e
|
45
45
|
end
|
46
46
|
Sunspot.index(post)
|
@@ -49,7 +49,7 @@ describe Sunspot::SessionProxy::Retry5xxSessionProxy do
|
|
49
49
|
it "should return the error response after two exceptions" do
|
50
50
|
fake_response = fake_rsolr_response(503)
|
51
51
|
e = FakeRSolrErrorHttp.new(fake_rsolr_request, fake_response)
|
52
|
-
fake_success =
|
52
|
+
fake_success = double('success')
|
53
53
|
|
54
54
|
@sunspot_session.should_receive(:index).and_return do
|
55
55
|
@sunspot_session.should_receive(:index).and_return do
|
@@ -6,7 +6,7 @@ describe Sunspot::SessionProxy::ShardingSessionProxy do
|
|
6
6
|
SUPPORTED_METHODS = Sunspot::SessionProxy::SilentFailSessionProxy::SUPPORTED_METHODS
|
7
7
|
|
8
8
|
before do
|
9
|
-
@search_session =
|
9
|
+
@search_session = double(Sunspot::Session.new)
|
10
10
|
@proxy = Sunspot::SessionProxy::SilentFailSessionProxy.new(@search_session)
|
11
11
|
end
|
12
12
|
|
@@ -54,6 +54,28 @@ module SearchHelper
|
|
54
54
|
}
|
55
55
|
end
|
56
56
|
|
57
|
+
def stub_stats(name, values)
|
58
|
+
connection.response = {
|
59
|
+
'stats' => {
|
60
|
+
'stats_fields' => {
|
61
|
+
name.to_s => { :facets => {} }.merge(values)
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def stub_stats_facets(name, facets)
|
68
|
+
connection.response = {
|
69
|
+
'stats' => {
|
70
|
+
'stats_fields' => {
|
71
|
+
name.to_s => {
|
72
|
+
'facets' => facets
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
57
79
|
def stub_query_facet(values)
|
58
80
|
connection.response = { 'facet_counts' => { 'facet_queries' => values } }
|
59
81
|
end
|
@@ -65,4 +87,12 @@ module SearchHelper
|
|
65
87
|
def facet_counts(result, field_name)
|
66
88
|
result.facet(field_name).rows.map { |row| row.count }
|
67
89
|
end
|
90
|
+
|
91
|
+
def stats_facet_values(result, field_name, facet_name)
|
92
|
+
result.stats(field_name).facet(facet_name).rows.map(&:value)
|
93
|
+
end
|
94
|
+
|
95
|
+
def stats_facet_stats(result, field_name, facet_name, value)
|
96
|
+
result.stats(field_name).facet(facet_name).rows.find { |r| r.value == value }
|
97
|
+
end
|
68
98
|
end
|