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,317 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+
3
+ describe 'keyword search' do
4
+ describe 'generally' do
5
+ before :all do
6
+ Sunspot.remove_all
7
+ @posts = []
8
+ @posts << Post.new(:title => 'The toast elects the insufficient spirit',
9
+ :body => 'Does the wind write?')
10
+ @posts << Post.new(:title => 'A nail abbreviates the recovering insight outside the moron',
11
+ :body => 'The interpreted strain scans the buffer around the upper temper')
12
+ @posts << Post.new(:title => 'The toast abbreviates the recovering spirit',
13
+ :body => 'Does the host\'s wind interpret the buffer, moron?')
14
+ Sunspot.index!(*@posts)
15
+ @comment = Namespaced::Comment.new(:body => 'Hey there where ya goin, not exactly knowin, who says you have to call just one place toast.')
16
+ Sunspot.index!(@comment)
17
+ end
18
+
19
+ it 'matches a single keyword out of a single field' do
20
+ results = Sunspot.search(Post) { keywords 'toast' }.results
21
+ [0, 2].each { |i| results.should include(@posts[i]) }
22
+ [1].each { |i| results.should_not include(@posts[i]) }
23
+ end
24
+
25
+ it 'matches multiple words out of a single field' do
26
+ results = Sunspot.search(Post) { keywords 'elects toast' }.results
27
+ results.should == [@posts[0]]
28
+ end
29
+
30
+ it 'matches multiple words in multiple fields' do
31
+ results = Sunspot.search(Post) { keywords 'toast wind' }.results
32
+ [0, 2].each { |i| results.should include(@posts[i]) }
33
+ [1].each { |i| results.should_not include(@posts[i]) }
34
+ end
35
+
36
+ it 'matches multiple types' do
37
+ results = Sunspot.search(Post, Namespaced::Comment) do
38
+ keywords 'toast'
39
+ end.results
40
+ [@posts[0], @posts[2], @comment].each { |obj| results.should include(obj) }
41
+ results.should_not include(@posts[1])
42
+ end
43
+
44
+ it 'matches keywords from only the fields specified' do
45
+ results = Sunspot.search(Post) do
46
+ keywords 'moron', :fields => [:title]
47
+ end.results
48
+ results.should == [@posts[1]]
49
+ end
50
+
51
+ it 'matches multiple keywords on different fields using subqueries' do
52
+ search = Sunspot.search(Post) do
53
+ keywords 'moron', :fields => [:title]
54
+ keywords 'wind', :fields => [:body]
55
+ end
56
+ search.results.should == []
57
+
58
+ search = Sunspot.search(Post) do
59
+ keywords 'moron', :fields => [:title]
60
+ keywords 'buffer', :fields => [:body]
61
+ end
62
+ search.results.should == [@posts[1]]
63
+ end
64
+
65
+ it 'matches multiple keywords with escaped characters' do
66
+ search = Sunspot.search(Post) do
67
+ keywords 'spirit', :fields => [:title]
68
+ keywords 'host\'s', :fields => [:body]
69
+ end
70
+ search.results.should == [@posts[2]]
71
+ end
72
+
73
+ it 'matches multiple keywords with phrase-based search' do
74
+ search = Sunspot.search(Post) do
75
+ keywords 'spirit', :fields => [:title]
76
+ keywords '"interpret the buffer"', :fields => [:body]
77
+ keywords '"does the"', :fields => [:body]
78
+ end
79
+ search.results.should == [@posts[2]]
80
+ end
81
+
82
+ it 'matches multiple keywords different options' do
83
+ search = Sunspot.search(Post) do
84
+ keywords 'insufficient nonexistent', :fields => [:title], :minimum_match => 1
85
+ keywords 'wind does', :fields => [:body], :minimum_match => 2
86
+ end
87
+ search.results.should == [@posts[0]]
88
+ end
89
+ end
90
+
91
+ describe 'with field boost' do
92
+ before :all do
93
+ Sunspot.remove_all
94
+ @posts = [:title, :body].map { |field| Post.new(field => 'rhinoceros') }
95
+ Sunspot.index!(*@posts)
96
+ end
97
+
98
+ it 'should assign a higher score to the result matching the higher-boosted field' do
99
+ search = Sunspot.search(Post) { keywords 'rhinoceros' }
100
+ search.hits.map { |hit| hit.primary_key }.should ==
101
+ @posts.map { |post| post.id.to_s }
102
+ search.hits.first.score.should > search.hits.last.score
103
+ end
104
+ end
105
+
106
+ describe 'with document boost' do
107
+ before :all do
108
+ Sunspot.remove_all
109
+ @posts = [4.0, 2.0].map do |rating|
110
+ Post.new(:title => 'Test', :ratings_average => rating)
111
+ end
112
+ Sunspot.index!(*@posts)
113
+ end
114
+
115
+ it 'should assign a higher score to the higher-boosted document' do
116
+ search = Sunspot.search(Post) { keywords 'test' }
117
+ search.hits.map { |hit| hit.primary_key }.should ==
118
+ @posts.map { |post| post.id.to_s }
119
+ search.hits.first.score.should > search.hits.last.score
120
+ end
121
+ end
122
+
123
+ describe 'with search-time boost' do
124
+ before :each do
125
+ Sunspot.remove_all
126
+ @comments = [
127
+ Namespaced::Comment.new(:body => 'test text'),
128
+ Namespaced::Comment.new(:author_name => 'test text')
129
+ ]
130
+ Sunspot.index!(@comments)
131
+ end
132
+
133
+ it 'assigns a higher score to documents in which all words appear in the phrase field' do
134
+ hits = Sunspot.search(Namespaced::Comment) do
135
+ keywords 'test text' do
136
+ phrase_fields :body => 2.0
137
+ end
138
+ end.hits
139
+ hits.first.instance.should == @comments.first
140
+ hits.first.score.should > hits.last.score
141
+ end
142
+
143
+ it 'assigns a higher score to documents in which the search terms appear in a boosted field' do
144
+ hits = Sunspot.search(Namespaced::Comment) do
145
+ keywords 'test' do
146
+ fields :body => 2.0, :author_name => 0.75
147
+ end
148
+ end.hits
149
+ hits.first.instance.should == @comments.first
150
+ hits.first.score.should > hits.last.score
151
+ end
152
+
153
+ it 'assigns a higher score to documents in which the search terms appear in a higher boosted phrase field' do
154
+ hits = Sunspot.search(Namespaced::Comment) do
155
+ keywords 'test text' do
156
+ phrase_fields :body => 2.0, :author_name => 0.75
157
+ end
158
+ end.hits
159
+ hits.first.instance.should == @comments.first
160
+ hits.first.score.should > hits.last.score
161
+ end
162
+ end
163
+
164
+ describe 'boost query' do
165
+ before :all do
166
+ Sunspot.remove_all
167
+ Sunspot.index!(
168
+ @posts = [
169
+ Post.new(:title => 'Rhino', :featured => true),
170
+ Post.new(:title => 'Rhino', :ratings_average => 3.3),
171
+ Post.new(:title => 'Rhino')
172
+ ]
173
+ )
174
+ end
175
+
176
+ it 'should assign a higher score to the document matching the boost query' do
177
+ search = Sunspot.search(Post) do |query|
178
+ query.keywords('rhino') do
179
+ boost(2.0) do
180
+ with(:featured, true)
181
+ end
182
+ end
183
+ query.without(@posts[1])
184
+ end
185
+ search.results.should == [@posts[0], @posts[2]]
186
+ search.hits[0].score.should > search.hits[1].score
187
+ end
188
+
189
+ it 'should assign scores in order of multiple boost query match' do
190
+ search = Sunspot.search(Post) do
191
+ keywords 'rhino' do
192
+ boost(2.0) { with(:featured, true) }
193
+ boost(1.5) { with(:average_rating).greater_than(3.0) }
194
+ end
195
+ end
196
+ search.results.should == @posts
197
+ search.hits[0].score.should > search.hits[1].score
198
+ search.hits[1].score.should > search.hits[2].score
199
+ end
200
+ end
201
+
202
+ describe 'minimum match' do
203
+ before do
204
+ Sunspot.remove_all
205
+ @posts = [
206
+ Post.new(:title => 'Pepperoni Sausage Anchovies'),
207
+ Post.new(:title => 'Pepperoni Tomatoes Mushrooms')
208
+ ]
209
+ Sunspot.index!(@posts)
210
+ @search = Sunspot.search(Post) do
211
+ keywords 'pepperoni sausage extra cheese', :minimum_match => 2
212
+ end
213
+ end
214
+
215
+ it 'should match documents that contain the minimum_match number of search terms' do
216
+ @search.results.should include(@posts[0])
217
+ end
218
+
219
+ it 'should not match documents that do not contain the minimum_match number of search terms' do
220
+ @search.results.should_not include(@posts[1])
221
+ end
222
+ end
223
+
224
+ describe 'query phrase slop' do
225
+ before do
226
+ Sunspot.remove_all
227
+ @posts = [
228
+ Post.new(:title => 'One four'),
229
+ Post.new(:title => 'One three four'),
230
+ Post.new(:title => 'One two three four')
231
+ ]
232
+ Sunspot.index!(@posts)
233
+ @search = Sunspot.search(Post) do
234
+ keywords '"one four"', :query_phrase_slop => 1
235
+ end
236
+ end
237
+
238
+ it 'should match exact phrase' do
239
+ @search.results.should include(@posts[0])
240
+ end
241
+
242
+ it 'should match phrase divided by query phrase slop terms' do
243
+ @search.results.should include(@posts[1])
244
+ end
245
+
246
+ it 'should not match phrase divided by more than query phrase slop terms' do
247
+ @search.results.should_not include(@posts[2])
248
+ end
249
+ end
250
+
251
+ describe 'phrase field slop' do
252
+ before do
253
+ Sunspot.remove_all
254
+ @comments = [
255
+ Namespaced::Comment.new(:author_name => 'one four'),
256
+ Namespaced::Comment.new(:body => 'one four'),
257
+ Namespaced::Comment.new(:author_name => 'one three four'),
258
+ Namespaced::Comment.new(:body => 'one three four'),
259
+ Namespaced::Comment.new(:author_name => 'one two three four'),
260
+ Namespaced::Comment.new(:body => 'one two three four')
261
+ ]
262
+ Sunspot.index!(@comments)
263
+ @search = Sunspot.search(Namespaced::Comment) do
264
+ keywords 'one four' do
265
+ phrase_fields :author_name => 3.0
266
+ phrase_slop 1
267
+ end
268
+ end
269
+ @sorted_hits = @search.hits.sort_by { |hit| @comments.index(hit.instance) }
270
+ end
271
+
272
+ it 'should give phrase field boost to exact match' do
273
+ @sorted_hits[0].score.should > @sorted_hits[1].score
274
+ end
275
+
276
+ it 'should give phrase field boost to match within slop' do
277
+ @sorted_hits[2].score.should > @sorted_hits[3].score
278
+ end
279
+
280
+ it 'should not give phrase field boost to match beyond slop' do
281
+ @sorted_hits[4].score.should == @sorted_hits[5].score
282
+ end
283
+ end
284
+
285
+ describe 'with function queries' do
286
+ before :each do
287
+ Sunspot.remove_all
288
+ end
289
+
290
+ after :each do
291
+ @search.results.should == @posts
292
+ @search.hits.first.score.should > @search.hits.last.score
293
+ end
294
+
295
+ it 'boosts via function query with float' do
296
+ @posts = [Post.new(:title => 'test', :ratings_average => 4.0),
297
+ Post.new(:title => 'test', :ratings_average => 2.0)]
298
+ Sunspot.index!(@posts)
299
+ @search = Sunspot.search(Post) do
300
+ keywords('test') do
301
+ boost function { :average_rating }
302
+ end
303
+ end
304
+ end
305
+
306
+ it 'boosts via function query with date' do
307
+ @posts = [Post.new(:title => 'test', :published_at => Time.now),
308
+ Post.new(:title => 'test', :published_at => Time.now - 60*60*24*31*6)] # roughly six months ago
309
+ Sunspot.index!(@posts)
310
+ @search = Sunspot.search(Post) do
311
+ keywords('test') do
312
+ boost function { recip(ms(Time.now, :published_at), 3.16e-11, 1, 1) }
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end
@@ -0,0 +1,64 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+
3
+ describe 'local search' do
4
+ ORIGIN = [40.7246062, -73.9969018]
5
+ LOCATIONS = [
6
+ [40.7246062, -73.9969018], # dr5rsjtn50yf
7
+ [40.724606, -73.996902], # dr5rsjtn50y9
8
+ [40.724606, -73.996901], # dr5rsjtn50z3
9
+ [40.72461, -73.996906] # dr5rsjtn51ec
10
+ ].map { |lat, lng| Sunspot::Util::Coordinates.new(lat, lng) }
11
+
12
+ before :each do
13
+ Sunspot.remove_all
14
+ end
15
+
16
+ describe 'without fulltext' do
17
+ before :each do
18
+ @posts = LOCATIONS.map do |location|
19
+ Post.new(:coordinates => location)
20
+ end
21
+ Sunspot.index!(@posts)
22
+ @search = Sunspot.search(Post) do
23
+ with(:coordinates).near(ORIGIN[0], ORIGIN[1], :precision_factor => 4.0)
24
+ end
25
+ end
26
+
27
+ it 'should return results in geo order' do
28
+ @search.results.should == @posts
29
+ end
30
+
31
+ it 'should asssign higher score to closer locations' do
32
+ hits = @search.hits
33
+ hits[1..-1].each_with_index do |hit, i|
34
+ hit.score.should < hits[i].score
35
+ end
36
+ end
37
+ end
38
+
39
+ describe 'with fulltext' do
40
+ before :each do
41
+ @posts = [
42
+ Post.new(:title => 'pizza', :coordinates => LOCATIONS[0]),
43
+ Post.new(:title => 'pizza', :coordinates => LOCATIONS[1]),
44
+ Post.new(:title => 'pasta calzone pizza antipasti', :coordinates => LOCATIONS[1])
45
+ ]
46
+ Sunspot.index!(@posts)
47
+ @search = Sunspot.search(Post) do
48
+ keywords 'pizza'
49
+ with(:coordinates).near(ORIGIN[0], ORIGIN[1])
50
+ end
51
+ end
52
+
53
+ it 'should take both fulltext and distance into account in ordering' do
54
+ @search.results.should == @posts
55
+ end
56
+
57
+ it 'should take both fulltext and distance into account in scoring' do
58
+ hits = @search.hits
59
+ hits[1..-1].each_with_index do |hit, i|
60
+ hit.score.should < hits[i].score
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+
3
+ describe 'more_like_this' do
4
+ before :all do
5
+ Sunspot.remove_all
6
+ @posts = [
7
+ Post.new(:body => "one two three", :tags => %w(ruby sunspot rsolr)),
8
+ Post.new(:body => "four five six", :tags => %w(ruby solr lucene)),
9
+ Post.new(:body => "two three four", :tags => %w(python sqlalchemy)),
10
+ Post.new(:body => "three four five", :tags => %w(ruby sunspot mat)),
11
+ Post.new(:body => "six seven eight", :tags => %w(bogus airplane))
12
+ ]
13
+ Sunspot.index!(@posts)
14
+ end
15
+
16
+ it 'should return results for all MLT fields' do
17
+ Sunspot.more_like_this(@posts.first).results.to_set.should == @posts[1..3].to_set
18
+ end
19
+
20
+ it 'should return results for specified text field' do
21
+ Sunspot.more_like_this(@posts.first) do
22
+ fields :body
23
+ end.results.to_set.should == @posts[2..3].to_set
24
+ end
25
+
26
+ it 'should return empty result set if no results' do
27
+ Sunspot.more_like_this(@posts.last) do
28
+ with(:title, 'bogus')
29
+ end.results.should == []
30
+ end
31
+
32
+ describe 'when non-indexed object searched' do
33
+ before(:each) { @mlt = Sunspot.more_like_this(Post.new) }
34
+
35
+ it 'should return empty result set' do
36
+ @mlt.results.should == []
37
+ end
38
+
39
+ it 'shoult return a total of 0' do
40
+ @mlt.total.should == 0
41
+ end
42
+ end
43
+ end