DrMark-thinking-sphinx 1.1.15 → 1.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +22 -0
- data/VERSION.yml +4 -0
- data/lib/thinking_sphinx/active_record/scopes.rb +39 -0
- data/lib/thinking_sphinx/active_record.rb +27 -7
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +9 -3
- data/lib/thinking_sphinx/association.rb +4 -1
- data/lib/thinking_sphinx/attribute.rb +91 -30
- data/lib/thinking_sphinx/configuration.rb +51 -12
- data/lib/thinking_sphinx/deltas/datetime_delta.rb +2 -2
- data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
- data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +1 -1
- data/lib/thinking_sphinx/deltas/delayed_delta.rb +3 -0
- data/lib/thinking_sphinx/deploy/capistrano.rb +25 -8
- data/lib/thinking_sphinx/excerpter.rb +22 -0
- data/lib/thinking_sphinx/facet.rb +1 -1
- data/lib/thinking_sphinx/facet_search.rb +134 -0
- data/lib/thinking_sphinx/index.rb +2 -1
- data/lib/thinking_sphinx/rails_additions.rb +14 -0
- data/lib/thinking_sphinx/search.rb +599 -658
- data/lib/thinking_sphinx/search_methods.rb +421 -0
- data/lib/thinking_sphinx/source/internal_properties.rb +1 -1
- data/lib/thinking_sphinx/source/sql.rb +17 -13
- data/lib/thinking_sphinx/source.rb +6 -6
- data/lib/thinking_sphinx/tasks.rb +42 -8
- data/lib/thinking_sphinx.rb +82 -54
- data/rails/init.rb +14 -0
- data/spec/{unit → lib}/thinking_sphinx/active_record/delta_spec.rb +5 -5
- data/spec/{unit → lib}/thinking_sphinx/active_record/has_many_association_spec.rb +0 -0
- data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +96 -0
- data/spec/{unit → lib}/thinking_sphinx/active_record_spec.rb +51 -31
- data/spec/{unit → lib}/thinking_sphinx/association_spec.rb +4 -5
- data/spec/lib/thinking_sphinx/attribute_spec.rb +465 -0
- data/spec/{unit → lib}/thinking_sphinx/configuration_spec.rb +161 -29
- data/spec/{unit → lib}/thinking_sphinx/core/string_spec.rb +0 -0
- data/spec/lib/thinking_sphinx/excerpter_spec.rb +49 -0
- data/spec/lib/thinking_sphinx/facet_search_spec.rb +176 -0
- data/spec/{unit → lib}/thinking_sphinx/facet_spec.rb +24 -0
- data/spec/{unit → lib}/thinking_sphinx/field_spec.rb +8 -8
- data/spec/{unit → lib}/thinking_sphinx/index/builder_spec.rb +6 -2
- data/spec/{unit → lib}/thinking_sphinx/index/faux_column_spec.rb +0 -0
- data/spec/lib/thinking_sphinx/index_spec.rb +45 -0
- data/spec/{unit → lib}/thinking_sphinx/rails_additions_spec.rb +25 -5
- data/spec/lib/thinking_sphinx/search_methods_spec.rb +152 -0
- data/spec/lib/thinking_sphinx/search_spec.rb +960 -0
- data/spec/{unit → lib}/thinking_sphinx/source_spec.rb +63 -2
- data/spec/{unit → lib}/thinking_sphinx_spec.rb +32 -4
- data/tasks/distribution.rb +36 -35
- data/vendor/riddle/lib/riddle/client/message.rb +4 -3
- data/vendor/riddle/lib/riddle/client.rb +3 -0
- data/vendor/riddle/lib/riddle/configuration/section.rb +8 -2
- data/vendor/riddle/lib/riddle/controller.rb +17 -7
- data/vendor/riddle/lib/riddle.rb +1 -1
- metadata +79 -83
- data/lib/thinking_sphinx/active_record/search.rb +0 -57
- data/lib/thinking_sphinx/collection.rb +0 -148
- data/lib/thinking_sphinx/facet_collection.rb +0 -59
- data/lib/thinking_sphinx/search/facets.rb +0 -98
- data/spec/unit/thinking_sphinx/active_record/search_spec.rb +0 -107
- data/spec/unit/thinking_sphinx/attribute_spec.rb +0 -232
- data/spec/unit/thinking_sphinx/collection_spec.rb +0 -14
- data/spec/unit/thinking_sphinx/facet_collection_spec.rb +0 -64
- data/spec/unit/thinking_sphinx/index_spec.rb +0 -139
- data/spec/unit/thinking_sphinx/search_spec.rb +0 -130
@@ -1,64 +0,0 @@
|
|
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
|
@@ -1,139 +0,0 @@
|
|
1
|
-
require 'spec/spec_helper'
|
2
|
-
|
3
|
-
describe ThinkingSphinx::Index do
|
4
|
-
describe "prefix_fields method" do
|
5
|
-
before :each do
|
6
|
-
@index = ThinkingSphinx::Index.new(Person)
|
7
|
-
|
8
|
-
@field_a = ThinkingSphinx::Field.stub_instance(:prefixes => true)
|
9
|
-
@field_b = ThinkingSphinx::Field.stub_instance(:prefixes => false)
|
10
|
-
@field_c = ThinkingSphinx::Field.stub_instance(:prefixes => true)
|
11
|
-
|
12
|
-
@index.stub_method(:fields => [@field_a, @field_b, @field_c])
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should return fields that are flagged as prefixed" do
|
16
|
-
@index.prefix_fields.should include(@field_a)
|
17
|
-
@index.prefix_fields.should include(@field_c)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should not return fields that aren't flagged as prefixed" do
|
21
|
-
@index.prefix_fields.should_not include(@field_b)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "infix_fields method" do
|
26
|
-
before :each do
|
27
|
-
@index = ThinkingSphinx::Index.new(Person)
|
28
|
-
|
29
|
-
@field_a = ThinkingSphinx::Field.stub_instance(:infixes => true)
|
30
|
-
@field_b = ThinkingSphinx::Field.stub_instance(:infixes => false)
|
31
|
-
@field_c = ThinkingSphinx::Field.stub_instance(:infixes => true)
|
32
|
-
|
33
|
-
@index.stub_method(:fields => [@field_a, @field_b, @field_c])
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should return fields that are flagged as infixed" do
|
37
|
-
@index.infix_fields.should include(@field_a)
|
38
|
-
@index.infix_fields.should include(@field_c)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should not return fields that aren't flagged as infixed" do
|
42
|
-
@index.infix_fields.should_not include(@field_b)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe "multi-value attribute as ranged-query with has-many association" do
|
47
|
-
before :each do
|
48
|
-
@index = ThinkingSphinx::Index::Builder.generate(Person) do
|
49
|
-
indexes first_name
|
50
|
-
has tags(:id), :as => :tag_ids, :source => :ranged_query
|
51
|
-
end
|
52
|
-
|
53
|
-
@sql = @index.sources.first.to_riddle_for_core(0, 0).sql_query
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should not include attribute in select-clause sql_query" do
|
57
|
-
@sql.should_not match(/tag_ids/)
|
58
|
-
@sql.should_not match(/GROUP_CONCAT\(`tags`.`id`/)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should not join with association table" do
|
62
|
-
@sql.should_not match(/LEFT OUTER JOIN `tags`/)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should include sql_attr_multi as ranged-query" do
|
66
|
-
attribute = @index.attributes.detect { |attrib| attrib.unique_name == :tag_ids }
|
67
|
-
attribute.type_to_config.should == :sql_attr_multi
|
68
|
-
|
69
|
-
declaration, query, range_query = attribute.send(:config_value).split('; ')
|
70
|
-
declaration.should == "uint tag_ids from ranged-query"
|
71
|
-
query.should == "SELECT `tags`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `tags`.`id` AS `tag_ids` FROM `tags` WHERE `tags`.`person_id` >= $start AND `tags`.`person_id` <= $end"
|
72
|
-
range_query.should == "SELECT MIN(`tags`.`person_id`), MAX(`tags`.`person_id`) FROM `tags`"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe "multi-value attribute as ranged-query with has-many-through association" do
|
77
|
-
before :each do
|
78
|
-
@index = ThinkingSphinx::Index::Builder.generate(Person) do
|
79
|
-
indexes first_name
|
80
|
-
has football_teams(:id), :as => :football_teams_ids, :source => :ranged_query
|
81
|
-
end
|
82
|
-
|
83
|
-
@sql = @index.sources.first.to_riddle_for_core(0, 0).sql_query
|
84
|
-
end
|
85
|
-
|
86
|
-
it "should not include attribute in select-clause sql_query" do
|
87
|
-
@sql.should_not match(/football_teams_ids/)
|
88
|
-
@sql.should_not match(/GROUP_CONCAT\(`tags`.`football_team_id`/)
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should not join with association table" do
|
92
|
-
@sql.should_not match(/LEFT OUTER JOIN `tags`/)
|
93
|
-
end
|
94
|
-
|
95
|
-
it "should include sql_attr_multi as ranged-query" do
|
96
|
-
attribute = @index.attributes.detect { |attrib|
|
97
|
-
attrib.unique_name == :football_teams_ids
|
98
|
-
}
|
99
|
-
attribute.type_to_config.should == :sql_attr_multi
|
100
|
-
|
101
|
-
declaration, query, range_query = attribute.send(:config_value).split('; ')
|
102
|
-
declaration.should == "uint football_teams_ids from ranged-query"
|
103
|
-
query.should == "SELECT `tags`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `tags`.`football_team_id` AS `football_teams_ids` FROM `tags` WHERE `tags`.`person_id` >= $start AND `tags`.`person_id` <= $end"
|
104
|
-
range_query.should == "SELECT MIN(`tags`.`person_id`), MAX(`tags`.`person_id`) FROM `tags`"
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe "multi-value attribute as ranged-query with has-many-through association and foreign_key" do
|
109
|
-
before :each do
|
110
|
-
@index = ThinkingSphinx::Index::Builder.generate(Person) do
|
111
|
-
indexes first_name
|
112
|
-
has friends(:id), :as => :friend_ids, :source => :ranged_query
|
113
|
-
end
|
114
|
-
|
115
|
-
@sql = @index.sources.first.to_riddle_for_core(0, 0).sql_query
|
116
|
-
end
|
117
|
-
|
118
|
-
it "should not include attribute in select-clause sql_query" do
|
119
|
-
@sql.should_not match(/friend_ids/)
|
120
|
-
@sql.should_not match(/GROUP_CONCAT\(`friendships`.`friend_id`/)
|
121
|
-
end
|
122
|
-
|
123
|
-
it "should not join with association table" do
|
124
|
-
@sql.should_not match(/LEFT OUTER JOIN `friendships`/)
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should include sql_attr_multi as ranged-query" do
|
128
|
-
attribute = @index.attributes.detect { |attrib|
|
129
|
-
attrib.unique_name == :friend_ids
|
130
|
-
}
|
131
|
-
attribute.type_to_config.should == :sql_attr_multi
|
132
|
-
|
133
|
-
declaration, query, range_query = attribute.send(:config_value).split('; ')
|
134
|
-
declaration.should == "uint friend_ids from ranged-query"
|
135
|
-
query.should == "SELECT `friendships`.`person_id` #{ThinkingSphinx.unique_id_expression} AS `id`, `friendships`.`friend_id` AS `friend_ids` FROM `friendships` WHERE `friendships`.`person_id` >= $start AND `friendships`.`person_id` <= $end"
|
136
|
-
range_query.should == "SELECT MIN(`friendships`.`person_id`), MAX(`friendships`.`person_id`) FROM `friendships`"
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
@@ -1,130 +0,0 @@
|
|
1
|
-
require 'spec/spec_helper'
|
2
|
-
require 'will_paginate/collection'
|
3
|
-
|
4
|
-
describe ThinkingSphinx::Search do
|
5
|
-
describe "search method" do
|
6
|
-
before :each do
|
7
|
-
@client = Riddle::Client.stub_instance(
|
8
|
-
:filters => [],
|
9
|
-
:filters= => true,
|
10
|
-
:id_range= => true,
|
11
|
-
:sort_mode => :asc,
|
12
|
-
:limit => 5,
|
13
|
-
:offset= => 0,
|
14
|
-
:sort_mode= => true,
|
15
|
-
:query => {
|
16
|
-
:matches => [],
|
17
|
-
:total => 50
|
18
|
-
}
|
19
|
-
)
|
20
|
-
|
21
|
-
ThinkingSphinx::Search.stub_methods(
|
22
|
-
:client_from_options => @client,
|
23
|
-
:search_conditions => ["", []]
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
describe ":star option" do
|
28
|
-
|
29
|
-
it "should not apply by default" do
|
30
|
-
ThinkingSphinx::Search.search "foo bar"
|
31
|
-
@client.should have_received(:query).with("foo bar")
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should apply when passed, and handle full extended syntax" do
|
35
|
-
input = %{a b* c (d | e) 123 5&6 (f_f g) !h "i j" "k l"~10 "m n"/3 @o p -(q|r)}
|
36
|
-
expected = %{*a* b* *c* (*d* | *e*) *123* *5*&*6* (*f_f* *g*) !*h* "i j" "k l"~10 "m n"/3 @o *p* -(*q*|*r*)}
|
37
|
-
ThinkingSphinx::Search.search input, :star => true
|
38
|
-
@client.should have_received(:query).with(expected)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should default to /\w+/ as token" do
|
42
|
-
ThinkingSphinx::Search.search "foo@bar.com", :star => true
|
43
|
-
@client.should have_received(:query).with("*foo*@*bar*.*com*")
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should honour custom token" do
|
47
|
-
ThinkingSphinx::Search.search "foo@bar.com -foo-bar", :star => /[\w@.-]+/u
|
48
|
-
@client.should have_received(:query).with("*foo@bar.com* -*foo-bar*")
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
describe "facets method" do
|
55
|
-
before :each do
|
56
|
-
@person = Person.find(:first)
|
57
|
-
|
58
|
-
@city_results = [@person]
|
59
|
-
@city_results.stub!(:each_with_groupby_and_count).
|
60
|
-
and_yield(@person, @person.city.to_crc32, 1)
|
61
|
-
|
62
|
-
@birthday_results = [@person]
|
63
|
-
@birthday_results.stub!(:each_with_groupby_and_count).
|
64
|
-
and_yield(@person, @person.birthday.to_i, 1)
|
65
|
-
|
66
|
-
ThinkingSphinx::Search.stub!(:search).and_return(@city_results, @birthday_results)
|
67
|
-
|
68
|
-
@config = ThinkingSphinx::Configuration.instance
|
69
|
-
@config.configuration.searchd.max_matches = 10_000
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should use the system-set max_matches for limit on facet calls" do
|
73
|
-
ThinkingSphinx::Search.should_receive(:search) do |options|
|
74
|
-
options[:max_matches].should == 10_000
|
75
|
-
options[:limit].should == 10_000
|
76
|
-
end
|
77
|
-
|
78
|
-
ThinkingSphinx::Search.facets :all_attributes => true
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should use the default max-matches if there is no explicit setting" do
|
82
|
-
@config.configuration.searchd.max_matches = nil
|
83
|
-
ThinkingSphinx::Search.should_receive(:search) do |options|
|
84
|
-
options[:max_matches].should == 1000
|
85
|
-
options[:limit].should == 1000
|
86
|
-
end
|
87
|
-
|
88
|
-
ThinkingSphinx::Search.facets :all_attributes => true
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should ignore user-provided max_matches and limit on facet calls" do
|
92
|
-
ThinkingSphinx::Search.should_receive(:search) do |options|
|
93
|
-
options[:max_matches].should == 10_000
|
94
|
-
options[:limit].should == 10_000
|
95
|
-
end
|
96
|
-
|
97
|
-
ThinkingSphinx::Search.facets(
|
98
|
-
:all_attributes => true,
|
99
|
-
:max_matches => 500,
|
100
|
-
:limit => 200
|
101
|
-
)
|
102
|
-
end
|
103
|
-
|
104
|
-
describe "conflicting facets" do
|
105
|
-
before :each do
|
106
|
-
@index = ThinkingSphinx::Index::Builder.generate(Alpha) do
|
107
|
-
indexes :name
|
108
|
-
has :value, :as => :city, :facet => true
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
after :each do
|
113
|
-
Alpha.sphinx_facets.delete_at(-1)
|
114
|
-
Alpha.sphinx_indexes.delete_at(-1)
|
115
|
-
end
|
116
|
-
|
117
|
-
it "should raise an error if searching with facets of same name but different type" do
|
118
|
-
lambda {
|
119
|
-
ThinkingSphinx::Search.facets :all_attributes => true
|
120
|
-
}.should raise_error
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
describe ThinkingSphinx::Search, "playing nice with Search model" do
|
127
|
-
it "should not conflict with models called Search" do
|
128
|
-
lambda { Search.find(:all) }.should_not raise_error
|
129
|
-
end
|
130
|
-
end
|