gojee-sunspot 2.0.3 → 2.0.4

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 (178) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +5 -0
  3. data/History.txt +252 -0
  4. data/LICENSE +18 -0
  5. data/Rakefile +13 -0
  6. data/TODO +13 -0
  7. data/lib/light_config.rb +40 -0
  8. data/lib/sunspot/adapters.rb +265 -0
  9. data/lib/sunspot/batcher.rb +62 -0
  10. data/lib/sunspot/class_set.rb +23 -0
  11. data/lib/sunspot/composite_setup.rb +202 -0
  12. data/lib/sunspot/configuration.rb +53 -0
  13. data/lib/sunspot/data_extractor.rb +50 -0
  14. data/lib/sunspot/dsl/adjustable.rb +47 -0
  15. data/lib/sunspot/dsl/field_group.rb +57 -0
  16. data/lib/sunspot/dsl/field_query.rb +327 -0
  17. data/lib/sunspot/dsl/fields.rb +103 -0
  18. data/lib/sunspot/dsl/fulltext.rb +243 -0
  19. data/lib/sunspot/dsl/function.rb +27 -0
  20. data/lib/sunspot/dsl/functional.rb +44 -0
  21. data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
  22. data/lib/sunspot/dsl/paginatable.rb +32 -0
  23. data/lib/sunspot/dsl/query_facet.rb +36 -0
  24. data/lib/sunspot/dsl/restriction.rb +25 -0
  25. data/lib/sunspot/dsl/restriction_with_near.rb +160 -0
  26. data/lib/sunspot/dsl/scope.rb +217 -0
  27. data/lib/sunspot/dsl/search.rb +30 -0
  28. data/lib/sunspot/dsl/standard_query.rb +123 -0
  29. data/lib/sunspot/dsl.rb +5 -0
  30. data/lib/sunspot/field.rb +193 -0
  31. data/lib/sunspot/field_factory.rb +129 -0
  32. data/lib/sunspot/indexer.rb +136 -0
  33. data/lib/sunspot/query/abstract_field_facet.rb +52 -0
  34. data/lib/sunspot/query/bbox.rb +15 -0
  35. data/lib/sunspot/query/boost_query.rb +24 -0
  36. data/lib/sunspot/query/common_query.rb +96 -0
  37. data/lib/sunspot/query/composite_fulltext.rb +36 -0
  38. data/lib/sunspot/query/connective.rb +206 -0
  39. data/lib/sunspot/query/date_field_facet.rb +14 -0
  40. data/lib/sunspot/query/dismax.rb +132 -0
  41. data/lib/sunspot/query/field_facet.rb +41 -0
  42. data/lib/sunspot/query/field_group.rb +36 -0
  43. data/lib/sunspot/query/filter.rb +38 -0
  44. data/lib/sunspot/query/function_query.rb +52 -0
  45. data/lib/sunspot/query/geo.rb +53 -0
  46. data/lib/sunspot/query/geofilt.rb +16 -0
  47. data/lib/sunspot/query/highlighting.rb +62 -0
  48. data/lib/sunspot/query/more_like_this.rb +61 -0
  49. data/lib/sunspot/query/more_like_this_query.rb +12 -0
  50. data/lib/sunspot/query/pagination.rb +42 -0
  51. data/lib/sunspot/query/query_facet.rb +16 -0
  52. data/lib/sunspot/query/restriction.rb +262 -0
  53. data/lib/sunspot/query/scope.rb +9 -0
  54. data/lib/sunspot/query/sort.rb +109 -0
  55. data/lib/sunspot/query/sort_composite.rb +34 -0
  56. data/lib/sunspot/query/standard_query.rb +16 -0
  57. data/lib/sunspot/query/text_field_boost.rb +17 -0
  58. data/lib/sunspot/query.rb +11 -0
  59. data/lib/sunspot/schema.rb +151 -0
  60. data/lib/sunspot/search/abstract_search.rb +281 -0
  61. data/lib/sunspot/search/date_facet.rb +35 -0
  62. data/lib/sunspot/search/facet_row.rb +27 -0
  63. data/lib/sunspot/search/field_facet.rb +88 -0
  64. data/lib/sunspot/search/field_group.rb +32 -0
  65. data/lib/sunspot/search/group.rb +50 -0
  66. data/lib/sunspot/search/highlight.rb +38 -0
  67. data/lib/sunspot/search/hit.rb +150 -0
  68. data/lib/sunspot/search/hit_enumerable.rb +72 -0
  69. data/lib/sunspot/search/more_like_this_search.rb +31 -0
  70. data/lib/sunspot/search/paginated_collection.rb +57 -0
  71. data/lib/sunspot/search/query_facet.rb +67 -0
  72. data/lib/sunspot/search/standard_search.rb +21 -0
  73. data/lib/sunspot/search.rb +9 -0
  74. data/lib/sunspot/session.rb +262 -0
  75. data/lib/sunspot/session_proxy/abstract_session_proxy.rb +29 -0
  76. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +66 -0
  77. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +89 -0
  78. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +43 -0
  79. data/lib/sunspot/session_proxy/multicore_session_proxy.rb +67 -0
  80. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +222 -0
  81. data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +42 -0
  82. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +37 -0
  83. data/lib/sunspot/session_proxy.rb +95 -0
  84. data/lib/sunspot/setup.rb +350 -0
  85. data/lib/sunspot/text_field_setup.rb +29 -0
  86. data/lib/sunspot/type.rb +393 -0
  87. data/lib/sunspot/util.rb +252 -0
  88. data/lib/sunspot/version.rb +3 -0
  89. data/lib/sunspot.rb +579 -0
  90. data/log/.gitignore +1 -0
  91. data/pkg/.gitignore +1 -0
  92. data/script/console +10 -0
  93. data/spec/api/adapters_spec.rb +33 -0
  94. data/spec/api/batcher_spec.rb +112 -0
  95. data/spec/api/binding_spec.rb +50 -0
  96. data/spec/api/class_set_spec.rb +24 -0
  97. data/spec/api/hit_enumerable_spec.rb +47 -0
  98. data/spec/api/indexer/attributes_spec.rb +149 -0
  99. data/spec/api/indexer/batch_spec.rb +72 -0
  100. data/spec/api/indexer/dynamic_fields_spec.rb +42 -0
  101. data/spec/api/indexer/fixed_fields_spec.rb +57 -0
  102. data/spec/api/indexer/fulltext_spec.rb +43 -0
  103. data/spec/api/indexer/removal_spec.rb +53 -0
  104. data/spec/api/indexer/spec_helper.rb +1 -0
  105. data/spec/api/indexer_spec.rb +14 -0
  106. data/spec/api/query/advanced_manipulation_examples.rb +35 -0
  107. data/spec/api/query/connectives_examples.rb +189 -0
  108. data/spec/api/query/dsl_spec.rb +18 -0
  109. data/spec/api/query/dynamic_fields_examples.rb +165 -0
  110. data/spec/api/query/faceting_examples.rb +397 -0
  111. data/spec/api/query/fulltext_examples.rb +313 -0
  112. data/spec/api/query/function_spec.rb +79 -0
  113. data/spec/api/query/geo_examples.rb +68 -0
  114. data/spec/api/query/group_spec.rb +32 -0
  115. data/spec/api/query/highlighting_examples.rb +245 -0
  116. data/spec/api/query/more_like_this_spec.rb +140 -0
  117. data/spec/api/query/ordering_pagination_examples.rb +116 -0
  118. data/spec/api/query/scope_examples.rb +275 -0
  119. data/spec/api/query/spatial_examples.rb +27 -0
  120. data/spec/api/query/spec_helper.rb +1 -0
  121. data/spec/api/query/standard_spec.rb +29 -0
  122. data/spec/api/query/text_field_scoping_examples.rb +30 -0
  123. data/spec/api/query/types_spec.rb +20 -0
  124. data/spec/api/search/dynamic_fields_spec.rb +33 -0
  125. data/spec/api/search/faceting_spec.rb +360 -0
  126. data/spec/api/search/highlighting_spec.rb +69 -0
  127. data/spec/api/search/hits_spec.rb +131 -0
  128. data/spec/api/search/paginated_collection_spec.rb +36 -0
  129. data/spec/api/search/results_spec.rb +72 -0
  130. data/spec/api/search/search_spec.rb +23 -0
  131. data/spec/api/search/spec_helper.rb +1 -0
  132. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +85 -0
  133. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +30 -0
  134. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +41 -0
  135. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +77 -0
  136. data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +24 -0
  137. data/spec/api/session_proxy/spec_helper.rb +9 -0
  138. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +39 -0
  139. data/spec/api/session_spec.rb +232 -0
  140. data/spec/api/spec_helper.rb +3 -0
  141. data/spec/api/sunspot_spec.rb +29 -0
  142. data/spec/ext.rb +11 -0
  143. data/spec/helpers/indexer_helper.rb +17 -0
  144. data/spec/helpers/integration_helper.rb +8 -0
  145. data/spec/helpers/mock_session_helper.rb +13 -0
  146. data/spec/helpers/query_helper.rb +26 -0
  147. data/spec/helpers/search_helper.rb +68 -0
  148. data/spec/integration/dynamic_fields_spec.rb +57 -0
  149. data/spec/integration/faceting_spec.rb +251 -0
  150. data/spec/integration/field_grouping_spec.rb +66 -0
  151. data/spec/integration/geospatial_spec.rb +85 -0
  152. data/spec/integration/highlighting_spec.rb +44 -0
  153. data/spec/integration/indexing_spec.rb +55 -0
  154. data/spec/integration/keyword_search_spec.rb +317 -0
  155. data/spec/integration/local_search_spec.rb +64 -0
  156. data/spec/integration/more_like_this_spec.rb +43 -0
  157. data/spec/integration/scoped_search_spec.rb +354 -0
  158. data/spec/integration/stored_fields_spec.rb +12 -0
  159. data/spec/integration/test_pagination.rb +43 -0
  160. data/spec/integration/unicode_spec.rb +15 -0
  161. data/spec/mocks/adapters.rb +32 -0
  162. data/spec/mocks/blog.rb +3 -0
  163. data/spec/mocks/comment.rb +21 -0
  164. data/spec/mocks/connection.rb +126 -0
  165. data/spec/mocks/mock_adapter.rb +30 -0
  166. data/spec/mocks/mock_class_sharding_session_proxy.rb +24 -0
  167. data/spec/mocks/mock_record.rb +52 -0
  168. data/spec/mocks/mock_sharding_session_proxy.rb +15 -0
  169. data/spec/mocks/photo.rb +11 -0
  170. data/spec/mocks/post.rb +86 -0
  171. data/spec/mocks/super_class.rb +2 -0
  172. data/spec/mocks/user.rb +13 -0
  173. data/spec/spec_helper.rb +40 -0
  174. data/sunspot.gemspec +42 -0
  175. data/tasks/rdoc.rake +27 -0
  176. data/tasks/schema.rake +19 -0
  177. data/tasks/todo.rake +4 -0
  178. metadata +261 -3
@@ -0,0 +1,79 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ describe 'function query' do
4
+ it "should send query to solr with boost function" do
5
+ session.search Post do
6
+ keywords('pizza') do
7
+ boost(function { :average_rating })
8
+ end
9
+ end
10
+ connection.should have_last_search_including(:bf, 'average_rating_ft')
11
+ end
12
+
13
+ it "should handle boost function with constant float" do
14
+ session.search Post do
15
+ keywords('pizza') do
16
+ boost(function { 10.5 })
17
+ end
18
+ end
19
+ connection.should have_last_search_including(:bf, '10.5')
20
+ end
21
+
22
+ it "should handle boost function with time literal" do
23
+ session.search Post do
24
+ keywords('pizza') do
25
+ boost(function { Time.parse('2010-03-25 14:13:00 EDT') })
26
+ end
27
+ end
28
+ connection.should have_last_search_including(:bf, '2010-03-25T18:13:00Z')
29
+ end
30
+
31
+ it "should handle arbitrary functions in a function query block" do
32
+ session.search Post do
33
+ keywords('pizza') do
34
+ boost(function { product(:average_rating, 10) })
35
+ end
36
+ end
37
+ connection.should have_last_search_including(:bf, 'product(average_rating_ft,10)')
38
+ end
39
+
40
+ it "should handle the sub function in a function query block" do
41
+ session.search Post do
42
+ keywords('pizza') do
43
+ boost(function { sub(:average_rating, 10) })
44
+ end
45
+ end
46
+ connection.should have_last_search_including(:bf, 'sub(average_rating_ft,10)')
47
+ end
48
+
49
+ it "should handle nested functions in a function query block" do
50
+ session.search Post do
51
+ keywords('pizza') do
52
+ boost(function { product(:average_rating, sum(:average_rating, 20)) })
53
+ end
54
+ end
55
+ connection.should have_last_search_including(:bf, 'product(average_rating_ft,sum(average_rating_ft,20))')
56
+ end
57
+
58
+ # TODO SOLR 1.5
59
+ it "should raise ArgumentError if string literal passed" do
60
+ lambda do
61
+ session.search Post do
62
+ keywords('pizza') do
63
+ boost(function { "hello world" })
64
+ end
65
+ end
66
+ end.should raise_error(ArgumentError)
67
+ end
68
+
69
+ it "should raise UnrecognizedFieldError if bogus field name passed" do
70
+ lambda do
71
+ session.search Post do
72
+ keywords('pizza') do
73
+ boost(function { :bogus })
74
+ end
75
+ end
76
+ end.should raise_error(Sunspot::UnrecognizedFieldError)
77
+ end
78
+ end
79
+
@@ -0,0 +1,68 @@
1
+ require 'bigdecimal'
2
+
3
+ shared_examples_for 'geohash query' do
4
+ it 'searches for nearby points with defaults' do
5
+ search do
6
+ with(:coordinates).near(40.7, -73.5)
7
+ end
8
+ connection.should have_last_search_including(:q, build_geo_query)
9
+ end
10
+
11
+ it 'searches for nearby points with non-Float arguments' do
12
+ search do
13
+ with(:coordinates).near(BigDecimal.new('40.7'), BigDecimal.new('-73.5'))
14
+ end
15
+ connection.should have_last_search_including(:q, build_geo_query)
16
+ end
17
+
18
+ it 'searches for nearby points with given precision' do
19
+ search do
20
+ with(:coordinates).near(40.7, -73.5, :precision => 10)
21
+ end
22
+ connection.should have_last_search_including(:q, build_geo_query(:precision => 10))
23
+ end
24
+
25
+ it 'searches for nearby points with given precision factor' do
26
+ search do
27
+ with(:coordinates).near(40.7, -73.5, :precision_factor => 1.5)
28
+ end
29
+ connection.should have_last_search_including(:q, build_geo_query(:precision_factor => 1.5))
30
+ end
31
+
32
+ it 'searches for nearby points with given boost' do
33
+ search do
34
+ with(:coordinates).near(40.7, -73.5, :boost => 2.0)
35
+ end
36
+ connection.should have_last_search_including(:q, build_geo_query(:boost => 2.0))
37
+ end
38
+
39
+ it 'performs both dismax search and location search' do
40
+ search do
41
+ fulltext 'pizza', :fields => :title
42
+ with(:coordinates).near(40.7, -73.5)
43
+ end
44
+ expected =
45
+ "{!dismax fl='* score' qf='title_text'}pizza (#{build_geo_query})"
46
+ connection.should have_last_search_including(
47
+ :q,
48
+ %Q(_query_:"{!dismax qf='title_text'}pizza" (#{build_geo_query}))
49
+ )
50
+ end
51
+
52
+ private
53
+
54
+ def build_geo_query(options = {})
55
+ precision = options[:precision] || 7
56
+ precision_factor = options[:precision_factor] || 16.0
57
+ boost = options[:boost] || 1.0
58
+ hash = 'dr5xx3nytvgs'
59
+ (precision..12).map do |i|
60
+ phrase =
61
+ if i == 12 then hash
62
+ else "#{hash[0, i]}*"
63
+ end
64
+ precision_boost = Sunspot::Util.format_float(boost*precision_factor**(i-12.0), 3)
65
+ "coordinates_s:#{phrase}^#{precision_boost}"
66
+ end.reverse.join(' OR ')
67
+ end
68
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ describe "field grouping" do
4
+ it "sends grouping parameters to solr" do
5
+ session.search Post do
6
+ group :title
7
+ end
8
+
9
+ connection.should have_last_search_including(:group, "true")
10
+ connection.should have_last_search_including(:"group.field", "title_ss")
11
+ end
12
+
13
+ it "sends grouping limit parameters to solr" do
14
+ session.search Post do
15
+ group :title do
16
+ limit 2
17
+ end
18
+ end
19
+
20
+ connection.should have_last_search_including(:"group.limit", 2)
21
+ end
22
+
23
+ it "sends grouping sort parameters to solr" do
24
+ session.search Post do
25
+ group :title do
26
+ order_by :average_rating
27
+ end
28
+ end
29
+
30
+ connection.should have_last_search_including(:"group.sort", "average_rating_ft asc")
31
+ end
32
+ end
@@ -0,0 +1,245 @@
1
+ shared_examples_for "query with highlighting support" do
2
+ it 'should not send highlight parameter when highlight not requested' do
3
+ search do
4
+ keywords 'test'
5
+ end
6
+ connection.should_not have_last_search_with(:hl)
7
+ end
8
+
9
+ it 'should enable highlighting when highlighting requested as keywords argument' do
10
+ search do
11
+ keywords 'test', :highlight => true
12
+ end
13
+ connection.should have_last_search_with(:hl => 'on')
14
+ end
15
+
16
+ it 'should not set highlight fields parameter if highlight fields are not passed' do
17
+ search do
18
+ keywords 'test', :highlight => true, :fields => [:title]
19
+ end
20
+ connection.should_not have_last_search_with(:'hl.fl')
21
+ end
22
+
23
+ it 'should enable highlighting on multiple fields when highlighting requested as array of fields via keywords argument' do
24
+ search do
25
+ keywords 'test', :highlight => [:title, :body]
26
+ end
27
+
28
+ connection.should have_last_search_with(:hl => 'on', :'hl.fl' => %w(title_text body_textsv))
29
+ end
30
+
31
+ it 'should raise UnrecognizedFieldError if try to highlight unexisting field via keywords argument' do
32
+ lambda {
33
+ search do
34
+ keywords 'test', :highlight => [:unknown_field]
35
+ end
36
+ }.should raise_error(Sunspot::UnrecognizedFieldError)
37
+ end
38
+
39
+ it 'should enable highlighting on multiple fields when highlighting requested as list of fields via block call' do
40
+ search do
41
+ keywords 'test' do
42
+ highlight :title, :body
43
+ end
44
+ end
45
+
46
+ connection.should have_last_search_with(:hl => 'on', :'hl.fl' => %w(title_text body_textsv))
47
+ end
48
+
49
+ it 'should enable highlighting on multiple fields for multiple search types' do
50
+ session.search(Post, Namespaced::Comment) do
51
+ keywords 'test' do
52
+ highlight :body
53
+ end
54
+ end
55
+ connection.searches.last[:'hl.fl'].to_set.should == Set['body_text', 'body_textsv']
56
+ end
57
+
58
+ it 'should raise UnrecognizedFieldError if try to highlight unexisting field via block call' do
59
+ lambda {
60
+ search do
61
+ keywords 'test' do
62
+ highlight :unknown_field
63
+ end
64
+ end
65
+ }.should raise_error(Sunspot::UnrecognizedFieldError)
66
+ end
67
+
68
+ it 'should set internal formatting' do
69
+ search do
70
+ keywords 'test', :highlight => true
71
+ end
72
+ connection.should have_last_search_with(
73
+ :"hl.simple.pre" => '@@@hl@@@',
74
+ :"hl.simple.post" => '@@@endhl@@@'
75
+ )
76
+ end
77
+
78
+ it 'should set highlight fields from DSL' do
79
+ search do
80
+ keywords 'test' do
81
+ highlight :title
82
+ end
83
+ end
84
+ connection.should have_last_search_with(
85
+ :"hl.fl" => %w(title_text)
86
+ )
87
+ end
88
+
89
+ it 'should not set formatting params specific to fields if fields specified' do
90
+ search do
91
+ keywords 'test', :highlight => :body
92
+ end
93
+ connection.should have_last_search_with(
94
+ :"hl.simple.pre" => '@@@hl@@@',
95
+ :"hl.simple.post" => '@@@endhl@@@'
96
+ )
97
+ end
98
+
99
+ it 'should set maximum highlights per field' do
100
+ search do
101
+ keywords 'test' do
102
+ highlight :max_snippets => 3
103
+ end
104
+ end
105
+ connection.should have_last_search_with(
106
+ :"hl.snippets" => 3
107
+ )
108
+ end
109
+
110
+ it 'should set max snippets specific to highlight fields' do
111
+ search do
112
+ keywords 'test' do
113
+ highlight :title, :max_snippets => 3
114
+ end
115
+ end
116
+ connection.should have_last_search_with(
117
+ :"hl.fl" => %w(title_text),
118
+ :"f.title_text.hl.snippets" => 3
119
+ )
120
+ end
121
+
122
+ it 'should set the maximum size' do
123
+ search do
124
+ keywords 'text' do
125
+ highlight :fragment_size => 200
126
+ end
127
+ end
128
+ connection.should have_last_search_with(
129
+ :"hl.fragsize" => 200
130
+ )
131
+ end
132
+
133
+ it 'should set the maximum size for specific fields' do
134
+ search do
135
+ keywords 'text' do
136
+ highlight :title, :fragment_size => 200
137
+ end
138
+ end
139
+ connection.should have_last_search_with(
140
+ :"f.title_text.hl.fragsize" => 200
141
+ )
142
+ end
143
+
144
+ it 'enables merging of contiguous fragments' do
145
+ search do
146
+ keywords 'test' do
147
+ highlight :merge_contiguous_fragments => true
148
+ end
149
+ end
150
+ connection.should have_last_search_with(
151
+ :"hl.mergeContiguous" => 'true'
152
+ )
153
+ end
154
+
155
+ it 'enables merging of contiguous fragments for specific fields' do
156
+ search do
157
+ keywords 'test' do
158
+ highlight :title, :merge_contiguous_fragments => true
159
+ end
160
+ end
161
+ connection.should have_last_search_with(
162
+ :"f.title_text.hl.mergeContiguous" => 'true'
163
+ )
164
+ end
165
+
166
+ it 'enables use of phrase highlighter' do
167
+ search do
168
+ keywords 'test' do
169
+ highlight :phrase_highlighter => true
170
+ end
171
+ end
172
+ connection.should have_last_search_with(
173
+ :"hl.usePhraseHighlighter" => 'true'
174
+ )
175
+ end
176
+
177
+ it 'enables use of phrase highlighter for specific fields' do
178
+ search do
179
+ keywords 'test' do
180
+ highlight :title, :phrase_highlighter => true
181
+ end
182
+ end
183
+ connection.should have_last_search_with(
184
+ :"f.title_text.hl.usePhraseHighlighter" => 'true'
185
+ )
186
+ end
187
+
188
+ it 'requires field match if requested' do
189
+ search do
190
+ keywords 'test' do
191
+ highlight :phrase_highlighter => true, :require_field_match => true
192
+ end
193
+ end
194
+ connection.should have_last_search_with(
195
+ :"hl.requireFieldMatch" => 'true'
196
+ )
197
+ end
198
+
199
+ it 'requires field match for specified field if requested' do
200
+ search do
201
+ keywords 'test' do
202
+ highlight :title, :phrase_highlighter => true, :require_field_match => true
203
+ end
204
+ end
205
+ connection.should have_last_search_with(
206
+ :"f.title_text.hl.requireFieldMatch" => 'true'
207
+ )
208
+ end
209
+
210
+ it 'sets field specific params for different fields if different params given' do
211
+ search do
212
+ keywords 'test' do
213
+ highlight :title, :max_snippets => 2
214
+ highlight :body, :max_snippets => 1
215
+ end
216
+ end
217
+ connection.should have_last_search_with(
218
+ :"hl.fl" => %w(title_text body_textsv),
219
+ :"f.title_text.hl.snippets" => 2,
220
+ :"f.body_textsv.hl.snippets" => 1
221
+ )
222
+ end
223
+
224
+ it 'sets the formatter for highlight output' do
225
+ search do
226
+ keywords 'test' do
227
+ highlight :title, :formatter => 'formatter'
228
+ end
229
+ end
230
+ connection.should have_last_search_with(
231
+ :"f.title_text.hl.formatter" => 'formatter'
232
+ )
233
+ end
234
+
235
+ it 'sets the text snippet generator for highlighted text' do
236
+ search do
237
+ keywords 'test' do
238
+ highlight :title, :fragmenter => 'example_fragmenter'
239
+ end
240
+ end
241
+ connection.should have_last_search_with(
242
+ :"f.title_text.hl.fragmenter" => 'example_fragmenter'
243
+ )
244
+ end
245
+ end
@@ -0,0 +1,140 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ describe 'more_like_this' do
4
+ before :each do
5
+ connection.expected_handler = :mlt
6
+ end
7
+
8
+ it_should_behave_like "scoped query"
9
+ it_should_behave_like "facetable query"
10
+ it_should_behave_like "query with advanced manipulation"
11
+ it_should_behave_like "query with connective scope"
12
+ it_should_behave_like "query with dynamic field support"
13
+ it_should_behave_like "sortable query"
14
+ it_should_behave_like "query with text field scoping"
15
+
16
+ it 'should query passed in object' do
17
+ p = Post.new
18
+ session.more_like_this(p)
19
+ connection.should have_last_search_with(:q => "id:Post\\ #{p.id}")
20
+ end
21
+
22
+ it 'should use more_like_this fields if no fields specified' do
23
+ session.more_like_this(Post.new)
24
+ connection.searches.last[:"mlt.fl"].split(',').sort.should == %w(body_textsv tags_textv)
25
+ end
26
+
27
+ it 'should use more_like_this fields if specified' do
28
+ session.more_like_this(Post.new) do
29
+ fields :body
30
+ end
31
+ connection.should have_last_search_with(:"mlt.fl" => "body_textsv")
32
+ end
33
+
34
+ it 'assigns boosts to fields when specified' do
35
+ session.more_like_this(Post.new) do
36
+ fields :body, :tags => 8
37
+ end
38
+ connection.searches.last[:"mlt.fl"].split(',').sort.should == %w(body_textsv tags_textv)
39
+ connection.should have_last_search_with(:qf => "tags_textv^8")
40
+ end
41
+
42
+ it 'doesn\'t assign boosts to fields when not specified' do
43
+ session.more_like_this(Post.new) do
44
+ fields :body
45
+ end
46
+ connection.should_not have_last_search_with(:qf)
47
+ end
48
+
49
+ it 'should raise ArgumentError if a field is not setup for more_like_this' do
50
+ lambda do
51
+ session.more_like_this(Post.new) do
52
+ fields :title
53
+ end
54
+ end.should raise_error(ArgumentError)
55
+ end
56
+
57
+ it 'should accept options' do
58
+ session.more_like_this(Post.new) do
59
+ minimum_term_frequency 1
60
+ minimum_document_frequency 2
61
+ minimum_word_length 3
62
+ maximum_word_length 4
63
+ maximum_query_terms 5
64
+ boost_by_relevance false
65
+ end
66
+ connection.should have_last_search_with(:"mlt.mintf" => 1)
67
+ connection.should have_last_search_with(:"mlt.mindf" => 2)
68
+ connection.should have_last_search_with(:"mlt.minwl" => 3)
69
+ connection.should have_last_search_with(:"mlt.maxwl" => 4)
70
+ connection.should have_last_search_with(:"mlt.maxqt" => 5)
71
+ connection.should have_last_search_with(:"mlt.boost" => false)
72
+ end
73
+
74
+ it 'should accept short options' do
75
+ session.more_like_this(Post.new) do
76
+ mintf 1
77
+ mindf 2
78
+ minwl 3
79
+ maxwl 4
80
+ maxqt 5
81
+ boost true
82
+ end
83
+ connection.should have_last_search_with(:"mlt.mintf" => 1)
84
+ connection.should have_last_search_with(:"mlt.mindf" => 2)
85
+ connection.should have_last_search_with(:"mlt.minwl" => 3)
86
+ connection.should have_last_search_with(:"mlt.maxwl" => 4)
87
+ connection.should have_last_search_with(:"mlt.maxqt" => 5)
88
+ connection.should have_last_search_with(:"mlt.boost" => true)
89
+ end
90
+
91
+ it 'paginates using default per_page when page not provided' do
92
+ session.more_like_this(Post.new)
93
+ connection.should have_last_search_with(:rows => 30)
94
+ end
95
+
96
+ it 'paginates using default per_page when page provided' do
97
+ session.more_like_this(Post.new) do
98
+ paginate :page => 2
99
+ end
100
+ connection.should have_last_search_with(:rows => 30, :start => 30)
101
+ end
102
+
103
+ it 'paginates using provided per_page' do
104
+ session.more_like_this(Post.new) do
105
+ paginate :page => 4, :per_page => 15
106
+ end
107
+ connection.should have_last_search_with(:rows => 15, :start => 45)
108
+ end
109
+
110
+ it 'defaults to page 1 if no :page argument given' do
111
+ session.more_like_this(Post.new) do
112
+ paginate :per_page => 15
113
+ end
114
+ connection.should have_last_search_with(:rows => 15, :start => 0)
115
+ end
116
+
117
+ it 'paginates from string argument' do
118
+ session.more_like_this(Post.new) do
119
+ paginate :page => '3', :per_page => '15'
120
+ end
121
+ connection.should have_last_search_with(:rows => 15, :start => 30)
122
+ end
123
+
124
+ it "should send query to solr with adjusted parameters (keyword example)" do
125
+ session.more_like_this(Post.new) do
126
+ adjust_solr_params do |params|
127
+ params[:q] = 'new search'
128
+ params[:some] = 'param'
129
+ end
130
+ end
131
+ connection.should have_last_search_with(:q => 'new search')
132
+ connection.should have_last_search_with(:some => 'param')
133
+ end
134
+
135
+ private
136
+
137
+ def search(*args, &block)
138
+ session.more_like_this(Post.new, *args, &block)
139
+ end
140
+ end
@@ -0,0 +1,116 @@
1
+ shared_examples_for 'sortable query' do
2
+ it 'paginates using default per_page when page not provided' do
3
+ search
4
+ connection.should have_last_search_with(:rows => 30)
5
+ end
6
+
7
+ it 'paginates using default per_page when page provided' do
8
+ search do
9
+ paginate :page => 2
10
+ end
11
+ connection.should have_last_search_with(:rows => 30, :start => 30)
12
+ end
13
+
14
+ it 'paginates using provided per_page' do
15
+ search do
16
+ paginate :page => 4, :per_page => 15
17
+ end
18
+ connection.should have_last_search_with(:rows => 15, :start => 45)
19
+ end
20
+
21
+ it 'defaults to page 1 if no :page argument given' do
22
+ search do
23
+ paginate :per_page => 15
24
+ end
25
+ connection.should have_last_search_with(:rows => 15, :start => 0)
26
+ end
27
+
28
+ it 'paginates with an offset' do
29
+ search do
30
+ paginate :per_page => 15, :offset => 3
31
+ end
32
+ connection.should have_last_search_with(:rows => 15, :start => 3)
33
+ end
34
+
35
+ it 'paginates with an offset as a string' do
36
+ search do
37
+ paginate :per_page => 15, :offset => '3'
38
+ end
39
+ connection.should have_last_search_with(:rows => 15, :start => 3)
40
+ end
41
+
42
+ it 'paginates from string argument' do
43
+ search do
44
+ paginate :page => '3', :per_page => '15'
45
+ end
46
+ connection.should have_last_search_with(:rows => 15, :start => 30)
47
+ end
48
+
49
+ it 'orders by a single field' do
50
+ search do
51
+ order_by :average_rating, :desc
52
+ end
53
+ connection.should have_last_search_with(:sort => 'average_rating_ft desc')
54
+ end
55
+
56
+ it 'orders by multiple fields' do
57
+ search do
58
+ order_by :average_rating, :desc
59
+ order_by :sort_title, :asc
60
+ end
61
+ connection.should have_last_search_with(:sort => 'average_rating_ft desc, sort_title_s asc')
62
+ end
63
+
64
+ it 'orders by random' do
65
+ search do
66
+ order_by :random
67
+ end
68
+ connection.searches.last[:sort].should =~ /^random_\d+ asc$/
69
+ end
70
+
71
+ it 'orders by score' do
72
+ search do
73
+ order_by :score, :desc
74
+ end
75
+ connection.should have_last_search_with(:sort => 'score desc')
76
+ end
77
+
78
+ it 'orders by geodist' do
79
+ search do
80
+ order_by_geodist :coordinates_new, 32, -68, :desc
81
+ end
82
+ connection.should have_last_search_with(:sort => 'geodist(coordinates_new_ll,32,-68) desc')
83
+ end
84
+
85
+ it 'throws an ArgumentError if a bogus order direction is given' do
86
+ lambda do
87
+ search do
88
+ order_by :sort_title, :sideways
89
+ end
90
+ end.should raise_error(ArgumentError)
91
+ end
92
+
93
+ it 'throws an UnrecognizedFieldError if :distance is given for sort' do
94
+ lambda do
95
+ search do
96
+ order_by :distance, :asc
97
+ end
98
+ end.should raise_error(Sunspot::UnrecognizedFieldError)
99
+ end
100
+
101
+ it 'does not allow ordering by multiple-value fields' do
102
+ lambda do
103
+ search do
104
+ order_by :category_ids
105
+ end
106
+ end.should raise_error(ArgumentError)
107
+ end
108
+
109
+ it 'raises ArgumentError if bogus argument given to paginate' do
110
+ lambda do
111
+ search do
112
+ paginate :page => 4, :ugly => :puppy
113
+ end
114
+ end.should raise_error(ArgumentError)
115
+ end
116
+ end