DrMark-thinking-sphinx 1.1.15 → 1.2.5

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.
Files changed (63) hide show
  1. data/README.textile +22 -0
  2. data/VERSION.yml +4 -0
  3. data/lib/thinking_sphinx/active_record/scopes.rb +39 -0
  4. data/lib/thinking_sphinx/active_record.rb +27 -7
  5. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +9 -3
  6. data/lib/thinking_sphinx/association.rb +4 -1
  7. data/lib/thinking_sphinx/attribute.rb +91 -30
  8. data/lib/thinking_sphinx/configuration.rb +51 -12
  9. data/lib/thinking_sphinx/deltas/datetime_delta.rb +2 -2
  10. data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
  11. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +1 -1
  12. data/lib/thinking_sphinx/deltas/delayed_delta.rb +3 -0
  13. data/lib/thinking_sphinx/deploy/capistrano.rb +25 -8
  14. data/lib/thinking_sphinx/excerpter.rb +22 -0
  15. data/lib/thinking_sphinx/facet.rb +1 -1
  16. data/lib/thinking_sphinx/facet_search.rb +134 -0
  17. data/lib/thinking_sphinx/index.rb +2 -1
  18. data/lib/thinking_sphinx/rails_additions.rb +14 -0
  19. data/lib/thinking_sphinx/search.rb +599 -658
  20. data/lib/thinking_sphinx/search_methods.rb +421 -0
  21. data/lib/thinking_sphinx/source/internal_properties.rb +1 -1
  22. data/lib/thinking_sphinx/source/sql.rb +17 -13
  23. data/lib/thinking_sphinx/source.rb +6 -6
  24. data/lib/thinking_sphinx/tasks.rb +42 -8
  25. data/lib/thinking_sphinx.rb +82 -54
  26. data/rails/init.rb +14 -0
  27. data/spec/{unit → lib}/thinking_sphinx/active_record/delta_spec.rb +5 -5
  28. data/spec/{unit → lib}/thinking_sphinx/active_record/has_many_association_spec.rb +0 -0
  29. data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +96 -0
  30. data/spec/{unit → lib}/thinking_sphinx/active_record_spec.rb +51 -31
  31. data/spec/{unit → lib}/thinking_sphinx/association_spec.rb +4 -5
  32. data/spec/lib/thinking_sphinx/attribute_spec.rb +465 -0
  33. data/spec/{unit → lib}/thinking_sphinx/configuration_spec.rb +161 -29
  34. data/spec/{unit → lib}/thinking_sphinx/core/string_spec.rb +0 -0
  35. data/spec/lib/thinking_sphinx/excerpter_spec.rb +49 -0
  36. data/spec/lib/thinking_sphinx/facet_search_spec.rb +176 -0
  37. data/spec/{unit → lib}/thinking_sphinx/facet_spec.rb +24 -0
  38. data/spec/{unit → lib}/thinking_sphinx/field_spec.rb +8 -8
  39. data/spec/{unit → lib}/thinking_sphinx/index/builder_spec.rb +6 -2
  40. data/spec/{unit → lib}/thinking_sphinx/index/faux_column_spec.rb +0 -0
  41. data/spec/lib/thinking_sphinx/index_spec.rb +45 -0
  42. data/spec/{unit → lib}/thinking_sphinx/rails_additions_spec.rb +25 -5
  43. data/spec/lib/thinking_sphinx/search_methods_spec.rb +152 -0
  44. data/spec/lib/thinking_sphinx/search_spec.rb +960 -0
  45. data/spec/{unit → lib}/thinking_sphinx/source_spec.rb +63 -2
  46. data/spec/{unit → lib}/thinking_sphinx_spec.rb +32 -4
  47. data/tasks/distribution.rb +36 -35
  48. data/vendor/riddle/lib/riddle/client/message.rb +4 -3
  49. data/vendor/riddle/lib/riddle/client.rb +3 -0
  50. data/vendor/riddle/lib/riddle/configuration/section.rb +8 -2
  51. data/vendor/riddle/lib/riddle/controller.rb +17 -7
  52. data/vendor/riddle/lib/riddle.rb +1 -1
  53. metadata +79 -83
  54. data/lib/thinking_sphinx/active_record/search.rb +0 -57
  55. data/lib/thinking_sphinx/collection.rb +0 -148
  56. data/lib/thinking_sphinx/facet_collection.rb +0 -59
  57. data/lib/thinking_sphinx/search/facets.rb +0 -98
  58. data/spec/unit/thinking_sphinx/active_record/search_spec.rb +0 -107
  59. data/spec/unit/thinking_sphinx/attribute_spec.rb +0 -232
  60. data/spec/unit/thinking_sphinx/collection_spec.rb +0 -14
  61. data/spec/unit/thinking_sphinx/facet_collection_spec.rb +0 -64
  62. data/spec/unit/thinking_sphinx/index_spec.rb +0 -139
  63. 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