freelancing-god-thinking-sphinx 1.1.8 → 1.1.9
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.
- data/README +1 -0
- data/lib/thinking_sphinx.rb +1 -1
- data/lib/thinking_sphinx/facet.rb +14 -1
- data/lib/thinking_sphinx/facet_collection.rb +14 -14
- data/lib/thinking_sphinx/search.rb +14 -3
- data/spec/unit/thinking_sphinx/facet_collection_spec.rb +64 -0
- data/spec/unit/thinking_sphinx/facet_spec.rb +46 -0
- data/spec/unit/thinking_sphinx/search_spec.rb +44 -0
- metadata +6 -2
data/README
CHANGED
data/lib/thinking_sphinx.rb
CHANGED
|
@@ -9,10 +9,23 @@ module ThinkingSphinx
|
|
|
9
9
|
raise "Can't translate Facets on multiple-column field or attribute"
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
|
+
|
|
13
|
+
def self.name_for(facet)
|
|
14
|
+
case facet
|
|
15
|
+
when Facet
|
|
16
|
+
facet.name
|
|
17
|
+
when String, Symbol
|
|
18
|
+
facet.to_s.gsub(/(_facet|_crc)$/,'').to_sym
|
|
19
|
+
end
|
|
20
|
+
end
|
|
12
21
|
|
|
13
22
|
def name
|
|
14
23
|
reference.unique_name
|
|
15
24
|
end
|
|
25
|
+
|
|
26
|
+
def self.attribute_name_for(name)
|
|
27
|
+
name.to_s == 'class' ? 'class_crc' : "#{name}_facet"
|
|
28
|
+
end
|
|
16
29
|
|
|
17
30
|
def attribute_name
|
|
18
31
|
# @attribute_name ||= case @reference
|
|
@@ -55,4 +68,4 @@ module ThinkingSphinx
|
|
|
55
68
|
@reference.columns.first
|
|
56
69
|
end
|
|
57
70
|
end
|
|
58
|
-
end
|
|
71
|
+
end
|
|
@@ -5,22 +5,26 @@ module ThinkingSphinx
|
|
|
5
5
|
def initialize(arguments)
|
|
6
6
|
@arguments = arguments.clone
|
|
7
7
|
@attribute_values = {}
|
|
8
|
-
@
|
|
8
|
+
@facet_names = []
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def add_from_results(facet, results)
|
|
12
|
+
name = ThinkingSphinx::Facet.name_for(facet)
|
|
13
|
+
|
|
14
|
+
self[name] ||= {}
|
|
15
|
+
@attribute_values[name] ||= {}
|
|
16
|
+
@facet_names << name
|
|
17
|
+
|
|
18
|
+
return if results.empty?
|
|
19
|
+
|
|
12
20
|
facet = facet_from_object(results.first, facet) if facet.is_a?(String)
|
|
13
21
|
|
|
14
|
-
self[facet.name] ||= {}
|
|
15
|
-
@attribute_values[facet.name] ||= {}
|
|
16
|
-
@facets << facet
|
|
17
|
-
|
|
18
22
|
results.each_with_groupby_and_count { |result, group, count|
|
|
19
23
|
facet_value = facet.value(result, group)
|
|
20
24
|
|
|
21
|
-
self[
|
|
22
|
-
self[
|
|
23
|
-
@attribute_values[
|
|
25
|
+
self[name][facet_value] ||= 0
|
|
26
|
+
self[name][facet_value] += count
|
|
27
|
+
@attribute_values[name][facet_value] = group
|
|
24
28
|
}
|
|
25
29
|
end
|
|
26
30
|
|
|
@@ -30,7 +34,7 @@ module ThinkingSphinx
|
|
|
30
34
|
options[:with] ||= {}
|
|
31
35
|
|
|
32
36
|
hash.each do |key, value|
|
|
33
|
-
attrib =
|
|
37
|
+
attrib = ThinkingSphinx::Facet.attribute_name_for(key)
|
|
34
38
|
options[:with][attrib] = underlying_value key, value
|
|
35
39
|
end
|
|
36
40
|
|
|
@@ -49,12 +53,8 @@ module ThinkingSphinx
|
|
|
49
53
|
end
|
|
50
54
|
end
|
|
51
55
|
|
|
52
|
-
def facet_for_key(key)
|
|
53
|
-
@facets.detect { |facet| facet.name == key }
|
|
54
|
-
end
|
|
55
|
-
|
|
56
56
|
def facet_from_object(object, name)
|
|
57
57
|
object.sphinx_facets.detect { |facet| facet.attribute_name == name }
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
|
-
end
|
|
60
|
+
end
|
|
@@ -720,11 +720,11 @@ module ThinkingSphinx
|
|
|
720
720
|
|
|
721
721
|
def facets_for_model(klass, args, options)
|
|
722
722
|
hash = ThinkingSphinx::FacetCollection.new args + [options]
|
|
723
|
-
options = options.clone.merge!
|
|
723
|
+
options = options.clone.merge! facet_query_options
|
|
724
724
|
|
|
725
725
|
klass.sphinx_facets.inject(hash) do |hash, facet|
|
|
726
726
|
unless facet.name == :class && !options[:class_facet]
|
|
727
|
-
options[:group_by]
|
|
727
|
+
options[:group_by] = facet.attribute_name
|
|
728
728
|
hash.add_from_results facet, search(*(args + [options]))
|
|
729
729
|
end
|
|
730
730
|
|
|
@@ -735,7 +735,7 @@ module ThinkingSphinx
|
|
|
735
735
|
def facets_for_all_models(args, options)
|
|
736
736
|
options = GlobalFacetOptions.merge(options)
|
|
737
737
|
hash = ThinkingSphinx::FacetCollection.new args + [options]
|
|
738
|
-
options = options.merge!
|
|
738
|
+
options = options.merge! facet_query_options
|
|
739
739
|
|
|
740
740
|
facet_names(options).inject(hash) do |hash, name|
|
|
741
741
|
options[:group_by] = name
|
|
@@ -744,6 +744,17 @@ module ThinkingSphinx
|
|
|
744
744
|
end
|
|
745
745
|
end
|
|
746
746
|
|
|
747
|
+
def facet_query_options
|
|
748
|
+
config = ThinkingSphinx::Configuration.instance
|
|
749
|
+
max = config.configuration.searchd.max_matches || 1000
|
|
750
|
+
|
|
751
|
+
{
|
|
752
|
+
:group_function => :attr,
|
|
753
|
+
:limit => max,
|
|
754
|
+
:max_matches => max
|
|
755
|
+
}
|
|
756
|
+
end
|
|
757
|
+
|
|
747
758
|
def facet_classes(options)
|
|
748
759
|
options[:classes] || ThinkingSphinx.indexed_models.collect { |model|
|
|
749
760
|
model.constantize
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'spec/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ThinkingSphinx::FacetCollection do
|
|
4
|
+
before do
|
|
5
|
+
@facet_collection = ThinkingSphinx::FacetCollection.new([])
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# TODO fix nasty hack when we have internet!
|
|
9
|
+
def mock_results
|
|
10
|
+
return @results if defined? @results
|
|
11
|
+
@result = Person.find(:first)
|
|
12
|
+
@results = [@result]
|
|
13
|
+
@results.stub!(:each_with_groupby_and_count).and_yield(@result, @result.city.to_crc32, 1)
|
|
14
|
+
@results
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "#add_from_results" do
|
|
18
|
+
describe "with empty result set" do
|
|
19
|
+
before do
|
|
20
|
+
@facet_collection.add_from_results('attribute_facet', [])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should add key as attribute" do
|
|
24
|
+
@facet_collection.should have_key(:attribute)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should return an empty hash for the facet results" do
|
|
28
|
+
@facet_collection[:attribute].should be_empty
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "with non-empty result set" do
|
|
33
|
+
before do
|
|
34
|
+
@facet_collection.add_from_results('city_facet', mock_results)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should return a hash" do
|
|
38
|
+
@facet_collection.should be_a_kind_of(Hash)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should add key as attribute" do
|
|
42
|
+
@facet_collection.keys.should include(:city)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should return a hash" do
|
|
46
|
+
@facet_collection[:city].should == {@result.city => 1}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "#for" do
|
|
52
|
+
before do
|
|
53
|
+
@facet_collection.add_from_results('city_facet', mock_results)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should return the search results for the attribute and key pair" do
|
|
57
|
+
ThinkingSphinx::Search.should_receive(:search) do |options|
|
|
58
|
+
options[:with].should have_key('city_facet')
|
|
59
|
+
options[:with]['city_facet'].should == @result.city.to_crc32
|
|
60
|
+
end
|
|
61
|
+
@facet_collection.for(:city => @result.city)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'spec/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ThinkingSphinx::Facet do
|
|
4
|
+
describe ".name_for" do
|
|
5
|
+
it "should remove '_facet' from provided string and return a symbol" do
|
|
6
|
+
ThinkingSphinx::Facet.name_for('attribute_facet').should == :attribute
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should remove '_facet' from provided symbol" do
|
|
10
|
+
ThinkingSphinx::Facet.name_for(:attribute_facet).should == :attribute
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should return the name of the facet if a Facet is passed" do
|
|
14
|
+
facet = ThinkingSphinx::Facet.new(
|
|
15
|
+
ThinkingSphinx::Attribute.stub_instance(:unique_name => :attribute, :columns => ['attribute'])
|
|
16
|
+
)
|
|
17
|
+
ThinkingSphinx::Facet.name_for(facet).should == :attribute
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should return 'class' for special case name 'class_crc'" do
|
|
21
|
+
ThinkingSphinx::Facet.name_for(:class_crc).should == :class
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should cycle" do
|
|
25
|
+
ThinkingSphinx::Facet.name_for(ThinkingSphinx::Facet.attribute_name_for(:attribute)).should == :attribute
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe ".attribute_name_for" do
|
|
30
|
+
it "should append '_facet' to provided string" do
|
|
31
|
+
ThinkingSphinx::Facet.attribute_name_for('attribute').should == 'attribute_facet'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should append '_facet' to provided symbol and return a string" do
|
|
35
|
+
ThinkingSphinx::Facet.attribute_name_for(:attribute).should == 'attribute_facet'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should return 'class_crc' for special case attribute 'class'" do
|
|
39
|
+
ThinkingSphinx::Facet.attribute_name_for(:class).should == 'class_crc'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should cycle" do
|
|
43
|
+
ThinkingSphinx::Facet.attribute_name_for(ThinkingSphinx::Facet.name_for('attribute_facet')).should == 'attribute_facet'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -50,6 +50,50 @@ describe ThinkingSphinx::Search do
|
|
|
50
50
|
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
|
+
|
|
54
|
+
describe "facets method" do
|
|
55
|
+
before :each do
|
|
56
|
+
@results = [Person.find(:first)]
|
|
57
|
+
@results.stub!(:each_with_groupby_and_count).
|
|
58
|
+
and_yield(@results.first, @results.first.city.to_crc32, 1)
|
|
59
|
+
ThinkingSphinx::Search.stub!(:search => @results)
|
|
60
|
+
|
|
61
|
+
@config = ThinkingSphinx::Configuration.instance
|
|
62
|
+
@config.configuration.searchd.max_matches = 10_000
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should use the system-set max_matches for limit on facet calls" do
|
|
66
|
+
ThinkingSphinx::Search.should_receive(:search) do |options|
|
|
67
|
+
options[:max_matches].should == 10_000
|
|
68
|
+
options[:limit].should == 10_000
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
ThinkingSphinx::Search.facets :all_attributes => true
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should use the default max-matches if there is no explicit setting" do
|
|
75
|
+
@config.configuration.searchd.max_matches = nil
|
|
76
|
+
ThinkingSphinx::Search.should_receive(:search) do |options|
|
|
77
|
+
options[:max_matches].should == 1000
|
|
78
|
+
options[:limit].should == 1000
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
ThinkingSphinx::Search.facets :all_attributes => true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should ignore user-provided max_matches and limit on facet calls" do
|
|
85
|
+
ThinkingSphinx::Search.should_receive(:search) do |options|
|
|
86
|
+
options[:max_matches].should == 10_000
|
|
87
|
+
options[:limit].should == 10_000
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
ThinkingSphinx::Search.facets(
|
|
91
|
+
:all_attributes => true,
|
|
92
|
+
:max_matches => 500,
|
|
93
|
+
:limit => 200
|
|
94
|
+
)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
53
97
|
end
|
|
54
98
|
|
|
55
99
|
describe ThinkingSphinx::Search, "playing nice with Search model" do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: freelancing-god-thinking-sphinx
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Pat Allan
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-05-
|
|
12
|
+
date: 2009-05-07 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|
|
@@ -109,6 +109,8 @@ files:
|
|
|
109
109
|
- spec/unit/thinking_sphinx/collection_spec.rb
|
|
110
110
|
- spec/unit/thinking_sphinx/configuration_spec.rb
|
|
111
111
|
- spec/unit/thinking_sphinx/core/string_spec.rb
|
|
112
|
+
- spec/unit/thinking_sphinx/facet_collection_spec.rb
|
|
113
|
+
- spec/unit/thinking_sphinx/facet_spec.rb
|
|
112
114
|
- spec/unit/thinking_sphinx/field_spec.rb
|
|
113
115
|
- spec/unit/thinking_sphinx/index/builder_spec.rb
|
|
114
116
|
- spec/unit/thinking_sphinx/index/faux_column_spec.rb
|
|
@@ -154,6 +156,8 @@ test_files:
|
|
|
154
156
|
- spec/unit/thinking_sphinx/collection_spec.rb
|
|
155
157
|
- spec/unit/thinking_sphinx/configuration_spec.rb
|
|
156
158
|
- spec/unit/thinking_sphinx/core/string_spec.rb
|
|
159
|
+
- spec/unit/thinking_sphinx/facet_collection_spec.rb
|
|
160
|
+
- spec/unit/thinking_sphinx/facet_spec.rb
|
|
157
161
|
- spec/unit/thinking_sphinx/field_spec.rb
|
|
158
162
|
- spec/unit/thinking_sphinx/index/builder_spec.rb
|
|
159
163
|
- spec/unit/thinking_sphinx/index/faux_column_spec.rb
|