outoftime-sunspot 0.8.9 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/README.rdoc +13 -21
  2. data/Rakefile +0 -2
  3. data/TODO +2 -15
  4. data/VERSION.yml +2 -2
  5. data/bin/sunspot-configure-solr +46 -0
  6. data/bin/sunspot-solr +15 -7
  7. data/lib/sunspot/adapters.rb +5 -1
  8. data/lib/sunspot/composite_setup.rb +186 -0
  9. data/lib/sunspot/configuration.rb +7 -1
  10. data/lib/sunspot/data_extractor.rb +10 -0
  11. data/lib/sunspot/date_facet.rb +36 -0
  12. data/lib/sunspot/date_facet_row.rb +17 -0
  13. data/lib/sunspot/dsl/field_query.rb +72 -0
  14. data/lib/sunspot/dsl/fields.rb +30 -3
  15. data/lib/sunspot/dsl/query.rb +16 -35
  16. data/lib/sunspot/dsl/query_facet.rb +31 -0
  17. data/lib/sunspot/dsl/scope.rb +76 -20
  18. data/lib/sunspot/dsl/search.rb +30 -0
  19. data/lib/sunspot/dsl.rb +1 -1
  20. data/lib/sunspot/facet.rb +17 -3
  21. data/lib/sunspot/facet_row.rb +4 -4
  22. data/lib/sunspot/field.rb +130 -207
  23. data/lib/sunspot/field_factory.rb +126 -0
  24. data/lib/sunspot/indexer.rb +61 -14
  25. data/lib/sunspot/instantiated_facet.rb +38 -0
  26. data/lib/sunspot/instantiated_facet_row.rb +12 -0
  27. data/lib/sunspot/query/base_query.rb +90 -0
  28. data/lib/sunspot/query/connective.rb +77 -0
  29. data/lib/sunspot/query/dynamic_query.rb +39 -56
  30. data/lib/sunspot/query/field_facet.rb +132 -4
  31. data/lib/sunspot/query/field_query.rb +57 -0
  32. data/lib/sunspot/query/pagination.rb +1 -1
  33. data/lib/sunspot/query/query_facet.rb +72 -0
  34. data/lib/sunspot/query/query_facet_row.rb +19 -0
  35. data/lib/sunspot/query/restriction.rb +9 -7
  36. data/lib/sunspot/query/scope.rb +165 -0
  37. data/lib/sunspot/query/sort.rb +17 -14
  38. data/lib/sunspot/query/sort_composite.rb +33 -0
  39. data/lib/sunspot/query.rb +162 -351
  40. data/lib/sunspot/query_facet.rb +33 -0
  41. data/lib/sunspot/query_facet_row.rb +21 -0
  42. data/lib/sunspot/schema.rb +165 -0
  43. data/lib/sunspot/search/hit.rb +62 -0
  44. data/lib/sunspot/search.rb +104 -41
  45. data/lib/sunspot/session.rb +64 -32
  46. data/lib/sunspot/setup.rb +119 -48
  47. data/lib/sunspot/type.rb +48 -2
  48. data/lib/sunspot.rb +74 -8
  49. data/solr/solr/conf/schema.xml +44 -225
  50. data/spec/api/build_search_spec.rb +557 -63
  51. data/spec/api/indexer_spec.rb +156 -74
  52. data/spec/api/query_spec.rb +55 -31
  53. data/spec/api/search_retrieval_spec.rb +210 -33
  54. data/spec/api/session_spec.rb +81 -26
  55. data/spec/api/sunspot_spec.rb +5 -7
  56. data/spec/integration/faceting_spec.rb +130 -0
  57. data/spec/integration/keyword_search_spec.rb +72 -31
  58. data/spec/integration/scoped_search_spec.rb +13 -0
  59. data/spec/integration/stored_fields_spec.rb +10 -0
  60. data/spec/mocks/blog.rb +3 -0
  61. data/spec/mocks/comment.rb +12 -23
  62. data/spec/mocks/connection.rb +84 -0
  63. data/spec/mocks/mock_adapter.rb +11 -3
  64. data/spec/mocks/mock_record.rb +41 -0
  65. data/spec/mocks/photo.rb +8 -0
  66. data/spec/mocks/post.rb +18 -23
  67. data/spec/spec_helper.rb +29 -14
  68. data/tasks/gemspec.rake +4 -3
  69. data/tasks/rdoc.rake +2 -2
  70. data/tasks/schema.rake +19 -0
  71. data/templates/schema.xml.haml +24 -0
  72. metadata +48 -7
  73. data/spec/mocks/base_class.rb +0 -2
@@ -2,137 +2,165 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe 'indexer' do
4
4
  describe 'when indexing an object' do
5
- it 'should index id and type' do
6
- connection.should_receive(:add).with([hash_including(:id => "Post #{post.id}", :type => ['Post', 'BaseClass'])])
5
+ it 'should index id' do
7
6
  session.index post
7
+ connection.should have_add_with(:id => "Post #{post.id}")
8
+ end
9
+
10
+ it 'should index type' do
11
+ session.index post
12
+ connection.should have_add_with(:type => ['Post', 'MockRecord'])
13
+ end
14
+
15
+ it 'should index class name' do
16
+ session.index post
17
+ connection.should have_add_with(:class_name => 'Post')
8
18
  end
9
19
 
10
20
  it 'should index the array of objects supplied' do
11
21
  posts = Array.new(2) { Post.new }
12
- connection.should_receive(:add).with([hash_including(:id => "Post #{posts.first.id}", :type => ['Post', 'BaseClass']),
13
- hash_including(:id => "Post #{posts.last.id}", :type => ['Post', 'BaseClass'])])
14
22
  session.index posts
23
+ connection.should have_add_with(
24
+ { :id => "Post #{posts.first.id}" },
25
+ { :id => "Post #{posts.last.id}" }
26
+ )
15
27
  end
16
28
 
17
29
  it 'should index an array containing more than one type of object' do
18
30
  post1, comment, post2 = objects = [Post.new, Namespaced::Comment.new, Post.new]
19
- connection.should_receive(:add).with([hash_including(:id => "Post #{post1.id}", :type => ['Post', 'BaseClass']),
20
- hash_including(:id => "Post #{post2.id}", :type => ['Post', 'BaseClass'])])
21
- connection.should_receive(:add).with([hash_including(:id => "Namespaced::Comment #{comment.id}", :type => ['Namespaced::Comment', 'BaseClass'])])
22
31
  session.index objects
32
+ connection.should have_add_with(
33
+ { :id => "Post #{post1.id}", :type => ['Post', 'MockRecord'] },
34
+ { :id => "Post #{post2.id}", :type => ['Post', 'MockRecord'] }
35
+ )
36
+ connection.should have_add_with(:id => "Namespaced::Comment #{comment.id}", :type => ['Namespaced::Comment', 'MockRecord'])
23
37
  end
24
38
 
25
39
  it 'should index text' do
26
- post :title => 'A Title', :body => 'A Post'
27
- connection.should_receive(:add).with([hash_including(:title_text => 'A Title', :body_text => 'A Post')])
28
- session.index post
40
+ session.index(post(:title => 'A Title', :body => 'A Post'))
41
+ connection.should have_add_with(:title_text => 'A Title', :body_text => 'A Post')
42
+ end
43
+
44
+ it 'should index text with boost' do
45
+ session.index(post(:title => 'A Title'))
46
+ connection.adds.last.first.field_by_name(:title_text).attrs[:boost].should == 2
47
+ end
48
+
49
+ it 'should index multiple values for a text field' do
50
+ session.index(post(:body => %w(some title)))
51
+ connection.should have_add_with(:body_text => %w(some title))
29
52
  end
30
53
 
31
54
  it 'should index text via a virtual field' do
32
- post :title => 'backwards'
33
- connection.should_receive(:add).with([hash_including(:backwards_title_text => 'backwards'.reverse)])
34
- session.index post
55
+ session.index(post(:title => 'backwards'))
56
+ connection.should have_add_with(:backwards_title_text => 'backwards'.reverse)
35
57
  end
36
58
 
37
- it 'should correctly index a string attribute field' do
38
- post :title => 'A Title'
39
- connection.should_receive(:add).with([hash_including(:title_s => 'A Title')])
40
- session.index post
59
+ it 'should correctly index a stored string attribute field' do
60
+ session.index(post(:title => 'A Title'))
61
+ connection.should have_add_with(:title_ss => 'A Title')
41
62
  end
42
63
 
43
64
  it 'should correctly index an integer attribute field' do
44
- post :blog_id => 4
45
- connection.should_receive(:add).with([hash_including(:blog_id_i => '4')])
46
- session.index post
65
+ session.index(post(:blog_id => 4))
66
+ connection.should have_add_with(:blog_id_i => '4')
47
67
  end
48
68
 
49
69
  it 'should correctly index a float attribute field' do
50
- post :ratings_average => 2.23
51
- connection.should_receive(:add).with([hash_including(:average_rating_f => '2.23')])
52
- session.index post
70
+ session.index(post(:ratings_average => 2.23))
71
+ connection.should have_add_with(:average_rating_f => '2.23')
53
72
  end
54
73
 
55
74
  it 'should allow indexing by a multiple-value field' do
56
- post :category_ids => [3, 14]
57
- connection.should_receive(:add).with([hash_including(:category_ids_im => ['3', '14'])])
58
- session.index post
75
+ session.index(post(:category_ids => [3, 14]))
76
+ connection.should have_add_with(:category_ids_im => ['3', '14'])
59
77
  end
60
78
 
61
79
  it 'should correctly index a time field' do
62
- post :published_at => Time.parse('1983-07-08 05:00:00 -0400')
63
- connection.should_receive(:add).with([hash_including(:published_at_d => '1983-07-08T09:00:00Z')])
64
- session.index post
80
+ session.index(
81
+ post(:published_at => Time.parse('1983-07-08 05:00:00 -0400'))
82
+ )
83
+ connection.should have_add_with(:published_at_d => '1983-07-08T09:00:00Z')
84
+ end
85
+
86
+ it 'should correctly index a date field' do
87
+ session.index(post(:expire_date => Date.new(2009, 07, 13)))
88
+ connection.should have_add_with(:expire_date_d => '2009-07-13T00:00:00Z')
65
89
  end
66
90
 
67
91
  it 'should correctly index a boolean field' do
68
- post :featured => true
69
- connection.should_receive(:add).with([hash_including(:featured_b => 'true')])
70
- session.index post
92
+ session.index(post(:featured => true))
93
+ connection.should have_add_with(:featured_b => 'true')
71
94
  end
72
95
 
73
96
  it 'should correctly index a false boolean field' do
74
- post :featured => false
75
- connection.should_receive(:add).with([hash_including(:featured_b => 'false')])
76
- session.index post
97
+ session.index(post(:featured => false))
98
+ connection.should have_add_with(:featured_b => 'false')
77
99
  end
78
100
 
79
101
  it 'should not index a nil boolean field' do
80
- post
81
- connection.should_receive(:add).with([hash_not_including(:featured_b)])
82
- session.index post
102
+ session.index(post)
103
+ connection.should_not have_add_with(:featured_b)
83
104
  end
84
105
 
85
106
  it 'should correctly index a virtual field' do
86
- post :title => 'The Blog Post'
87
- connection.should_receive(:add).with([hash_including(:sort_title_s => 'blog post')])
88
- session.index post
107
+ session.index(post(:title => 'The Blog Post'))
108
+ connection.should have_add_with(:sort_title_s => 'blog post')
89
109
  end
90
110
 
91
111
  it 'should correctly index an external virtual field' do
92
- post :category_ids => [1, 2, 3]
93
- connection.should_receive(:add).with([hash_including(:primary_category_id_i => '1')])
94
- session.index post
112
+ session.index(post(:category_ids => [1, 2, 3]))
113
+ connection.should have_add_with(:primary_category_id_i => '1')
95
114
  end
96
115
 
97
116
  it 'should correctly index a field that is defined on a superclass' do
98
- Sunspot.setup(BaseClass) { string :author_name }
99
- post :author_name => 'Mat Brown'
100
- connection.should_receive(:add).with([hash_including(:author_name_s => 'Mat Brown')])
101
- session.index post
117
+ Sunspot.setup(MockRecord) { string :author_name }
118
+ session.index(post(:author_name => 'Mat Brown'))
119
+ connection.should have_add_with(:author_name_s => 'Mat Brown')
102
120
  end
103
121
 
104
122
  it 'should commit immediately after index! called' do
105
- post :title => 'The Blog Post'
106
123
  connection.should_receive(:add).ordered
107
124
  connection.should_receive(:commit).ordered
108
125
  session.index!(post)
109
126
  end
110
127
 
111
128
  it 'should remove an object from the index' do
112
- connection.should_receive(:delete).with("Post #{post.id}")
113
129
  session.remove(post)
130
+ connection.should have_delete("Post #{post.id}")
131
+ end
132
+
133
+ it 'should remove an object by type and id' do
134
+ session.remove_by_id(Post, 1)
135
+ connection.should have_delete('Post 1')
136
+ end
137
+
138
+ it 'should remove an object by type and id and immediately commit' do
139
+ connection.should_receive(:delete_by_id).with('Post 1').ordered
140
+ connection.should_receive(:commit).ordered
141
+ session.remove_by_id!(Post, 1)
114
142
  end
115
143
 
116
144
  it 'should remove an object from the index and immediately commit' do
117
- connection.should_receive(:delete).with("Post #{post.id}").ordered
145
+ connection.should_receive(:delete_by_id).ordered
118
146
  connection.should_receive(:commit).ordered
119
147
  session.remove!(post)
120
148
  end
121
149
 
122
150
  it 'should remove everything from the index' do
123
- connection.should_receive(:delete_by_query).with("type:[* TO *]")
124
151
  session.remove_all
152
+ connection.should have_delete_by_query("type:[* TO *]")
125
153
  end
126
154
 
127
155
  it 'should remove everything from the index and immediately commit' do
128
- connection.should_receive(:delete_by_query).with("type:[* TO *]").ordered
156
+ connection.should_receive(:delete_by_query).ordered
129
157
  connection.should_receive(:commit).ordered
130
158
  session.remove_all!
131
159
  end
132
160
 
133
161
  it 'should be able to remove everything of a given class from the index' do
134
- connection.should_receive(:delete_by_query).with("type:Post")
135
162
  session.remove_all(Post)
163
+ connection.should have_delete_by_query("type:Post")
136
164
  end
137
165
 
138
166
  it 'should correctly escape namespaced classes when removing everything from the index' do
@@ -141,44 +169,86 @@ describe 'indexer' do
141
169
  end
142
170
  end
143
171
 
172
+ describe 'batches' do
173
+ it 'should send all batched adds in a single request' do
174
+ posts = Array.new(2) { Post.new }
175
+ session.batch do
176
+ for post in posts
177
+ session.index(post)
178
+ end
179
+ end
180
+ connection.adds.length.should == 1
181
+ end
182
+
183
+ it 'should add all batched adds' do
184
+ posts = Array.new(2) { Post.new }
185
+ session.batch do
186
+ for post in posts
187
+ session.index(post)
188
+ end
189
+ end
190
+ add = connection.adds.last
191
+ connection.adds.first.map { |add| add.field_by_name(:id).value }.should ==
192
+ posts.map { |post| "Post #{post.id}" }
193
+ end
194
+
195
+ it 'should not index changes to models that happen after index call' do
196
+ post = Post.new
197
+ session.batch do
198
+ session.index(post)
199
+ post.title = 'Title'
200
+ end
201
+ connection.adds.first.first.field_by_name(:title_ss).should be_nil
202
+ end
203
+ end
204
+
144
205
  describe 'dynamic fields' do
145
206
  it 'should index string data' do
146
- post(:custom_string => { :test => 'string' })
147
- connection.should_receive(:add).with([hash_including(:"custom_string:test_s" => 'string')])
148
- session.index(post)
207
+ session.index(post(:custom_string => { :test => 'string' }))
208
+ connection.should have_add_with(:"custom_string:test_s" => 'string')
149
209
  end
150
210
 
151
211
  it 'should index integer data with virtual accessor' do
152
- post(:category_ids => [1, 2])
153
- connection.should_receive(:add).with([hash_including(:"custom_integer:1_i" => '1', :"custom_integer:2_i" => '1')])
154
- session.index(post)
212
+ session.index(post(:category_ids => [1, 2]))
213
+ connection.should have_add_with(:"custom_integer:1_i" => '1', :"custom_integer:2_i" => '1')
155
214
  end
156
215
 
157
216
  it 'should index float data' do
158
- post(:custom_fl => { :test => 1.5 })
159
- connection.should_receive(:add).with([hash_including(:"custom_float:test_fm" => '1.5')])
160
- session.index(post)
217
+ session.index(post(:custom_fl => { :test => 1.5 }))
218
+ connection.should have_add_with(:"custom_float:test_fm" => '1.5')
161
219
  end
162
220
 
163
221
  it 'should index time data' do
164
- post(:custom_time => { :test => Time.parse('2009-05-18 18:05:00 -0400') })
165
- connection.should_receive(:add).with([hash_including(:"custom_time:test_d" => '2009-05-18T22:05:00Z')])
166
- session.index(post)
222
+ session.index(post(:custom_time => { :test => Time.parse('2009-05-18 18:05:00 -0400') }))
223
+ connection.should have_add_with(:"custom_time:test_d" => '2009-05-18T22:05:00Z')
167
224
  end
168
225
 
169
226
  it 'should index boolean data' do
170
- post(:custom_boolean => { :test => false })
171
- connection.should_receive(:add).with([hash_including(:"custom_boolean:test_b" => 'false')])
172
- session.index(post)
227
+ session.index(post(:custom_boolean => { :test => false }))
228
+ connection.should have_add_with(:"custom_boolean:test_b" => 'false')
173
229
  end
174
230
 
175
231
  it 'should index multiple values for a field' do
176
- post(:custom_fl => { :test => [1.0, 2.1, 3.2] })
177
- connection.should_receive(:add).with([hash_including(:"custom_float:test_fm" => %w(1.0 2.1 3.2))])
178
- session.index(post)
232
+ session.index(post(:custom_fl => { :test => [1.0, 2.1, 3.2] }))
233
+ connection.should have_add_with(:"custom_float:test_fm" => %w(1.0 2.1 3.2))
179
234
  end
180
235
  end
181
236
 
237
+ it 'should index document level boost using block' do
238
+ session.index(post(:ratings_average => 4.0))
239
+ connection.adds.last.first.attrs[:boost].should == 1.25
240
+ end
241
+
242
+ it 'should index document level boost using attribute' do
243
+ session.index(Namespaced::Comment.new(:boost => 1.5))
244
+ connection.adds.last.first.attrs[:boost].should == 1.5
245
+ end
246
+
247
+ it 'should index document level boost defined statically' do
248
+ session.index(Photo.new)
249
+ connection.adds.last.first.attrs[:boost].should == 0.75
250
+ end
251
+
182
252
  it 'should throw a NoMethodError only if a nonexistent type is defined' do
183
253
  lambda { Sunspot.setup(Post) { string :author_name }}.should_not raise_error
184
254
  lambda { Sunspot.setup(Post) { bogus :journey }}.should raise_error(NoMethodError)
@@ -189,7 +259,7 @@ describe 'indexer' do
189
259
  end
190
260
 
191
261
  it 'should throw an ArgumentError if an attempt is made to index an object that has no configuration' do
192
- lambda { session.index(Time.now) }.should raise_error(Sunspot::NoSetupError)
262
+ lambda { session.index(Blog.new) }.should raise_error(Sunspot::NoSetupError)
193
263
  end
194
264
 
195
265
  it 'should throw an ArgumentError if single-value field tries to index multiple values' do
@@ -216,7 +286,7 @@ describe 'indexer' do
216
286
  end
217
287
 
218
288
  def connection
219
- @connection ||= mock('connection')
289
+ @connection ||= Mock::Connection.new
220
290
  end
221
291
 
222
292
  def session
@@ -226,4 +296,16 @@ describe 'indexer' do
226
296
  def post(attrs = {})
227
297
  @post ||= Post.new(attrs)
228
298
  end
299
+
300
+ def last_add
301
+ @connection.adds.last
302
+ end
303
+
304
+ def value_in_last_document_for(field_name)
305
+ @connection.adds.last.last.field_by_name(field_name).value
306
+ end
307
+
308
+ def values_in_last_document_for(field_name)
309
+ @connection.adds.last.last.fields_by_name(field_name).map { |field| field.value }
310
+ end
229
311
  end
@@ -3,127 +3,151 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
3
3
  describe Sunspot::Query do
4
4
  before :each do
5
5
  @config ||= Sunspot::Configuration.build
6
- @connection ||= mock('connection')
6
+ @connection ||= Mock::Connection.new
7
7
  @session ||= Sunspot::Session.new(@config, @connection)
8
8
  @search = @session.new_search(Post)
9
9
  end
10
10
 
11
- after :each do
12
- @search.execute!
13
- end
14
-
15
11
  it 'should perform keyword search' do
16
12
  @search.query.keywords = 'keyword search'
17
- @connection.should_receive(:query).with('(keyword search) AND (type:Post)', hash_including)
13
+ @search.execute!
14
+ @connection.should have_last_search_with(:q => 'keyword search')
18
15
  end
19
16
 
20
17
  it 'should add equality restriction' do
21
18
  @search.query.add_restriction(:title, :equal_to, 'My Pet Post')
22
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['title_s:My\ Pet\ Post']))
19
+ @search.execute!
20
+ @connection.should have_last_search_with(:fq => ['title_ss:My\ Pet\ Post'])
23
21
  end
24
22
 
25
23
  it 'should add less than restriction' do
26
24
  @search.query.add_restriction(:average_rating, :less_than, 3.0)
27
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['average_rating_f:[* TO 3\.0]']))
25
+ @search.execute!
26
+ @connection.should have_last_search_with(:fq => ['average_rating_f:[* TO 3\.0]'])
28
27
  end
29
28
 
30
29
  it 'should add greater than restriction' do
31
30
  @search.query.add_restriction(:average_rating, :greater_than, 3.0)
32
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['average_rating_f:[3\.0 TO *]']))
31
+ @search.execute!
32
+ @connection.should have_last_search_with(:fq => ['average_rating_f:[3\.0 TO *]'])
33
33
  end
34
34
 
35
35
  it 'should add between restriction' do
36
36
  @search.query.add_restriction(:average_rating, :between, 2.0..4.0)
37
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['average_rating_f:[2\.0 TO 4\.0]']))
37
+ @search.execute!
38
+ @connection.should have_last_search_with(:fq => ['average_rating_f:[2\.0 TO 4\.0]'])
38
39
  end
39
40
 
40
41
  it 'should add any restriction' do
41
42
  @search.query.add_restriction(:category_ids, :any_of, [2, 7, 12])
42
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['category_ids_im:(2 OR 7 OR 12)']))
43
+ @search.execute!
44
+ @connection.should have_last_search_with(:fq => ['category_ids_im:(2 OR 7 OR 12)'])
43
45
  end
44
46
 
45
47
  it 'should add all restriction' do
46
48
  @search.query.add_restriction(:category_ids, :all_of, [2, 7, 12])
47
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['category_ids_im:(2 AND 7 AND 12)']))
49
+ @search.execute!
50
+ @connection.should have_last_search_with(:fq => ['category_ids_im:(2 AND 7 AND 12)'])
48
51
  end
49
52
 
50
53
  it 'should negate restriction' do
51
54
  @search.query.add_negated_restriction(:title, :equal_to, 'Bad Post')
52
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['-title_s:Bad\ Post']))
55
+ @search.execute!
56
+ @connection.should have_last_search_with(:fq => ['-title_ss:Bad\ Post'])
53
57
  end
54
58
 
55
59
  it 'should exclude instance' do
56
60
  post = Post.new
57
61
  @search.query.exclude_instance(post)
58
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ["-id:Post\\ #{post.id}"]))
62
+ @search.execute!
63
+ @connection.should have_last_search_with(:fq => ["-id:Post\\ #{post.id}"])
59
64
  end
60
65
 
61
66
  it 'should paginate using default per-page' do
62
67
  @search.query.paginate(2)
63
- @connection.should_receive(:query).with('(type:Post)', hash_including(:rows => 30, :start => 30))
68
+ @search.execute!
69
+ @connection.should have_last_search_with(:rows => 30)
64
70
  end
65
71
 
66
72
  it 'should paginate using provided per-page' do
67
73
  @search.query.paginate(4, 15)
68
- @connection.should_receive(:query).with('(type:Post)', hash_including(:rows => 15, :start => 45))
74
+ @search.execute!
75
+ @connection.should have_last_search_with(:rows => 15, :start => 45)
69
76
  end
70
77
 
71
78
  it 'should order ascending by default' do
72
79
  @search.query.order_by(:average_rating)
73
- @connection.should_receive(:query).with('(type:Post)', hash_including(:sort => [{ :average_rating_f => :ascending }]))
80
+ @search.execute!
81
+ @connection.should have_last_search_with(:sort => 'average_rating_f asc')
74
82
  end
75
83
 
76
84
  it 'should order descending if specified' do
77
85
  @search.query.order_by(:average_rating, :desc)
78
- @connection.should_receive(:query).with('(type:Post)', hash_including(:sort => [{ :average_rating_f => :descending }]))
86
+ @search.execute!
87
+ @connection.should have_last_search_with(:sort => 'average_rating_f desc')
79
88
  end
80
89
 
81
90
  it 'should request a field facet' do
82
91
  @search.query.add_field_facet(:category_ids)
83
- @connection.should_receive(:query).with('(type:Post)', hash_including(:facets => { :fields => %w(category_ids_im) }))
92
+ @search.execute!
93
+ @connection.should have_last_search_with(:"facet.field" => %w(category_ids_im))
84
94
  end
85
95
 
86
96
  it 'should restrict by dynamic string field with equality restriction' do
87
97
  @search.query.dynamic_query(:custom_string).add_restriction(:test, :equal_to, 'string')
88
- @connection.should_receive(:query).with('(type:Post)', hash_including(:filter_queries => ['custom_string\:test_s:string']))
98
+ @search.execute!
99
+ @connection.should have_last_search_with(:fq => ['custom_string\:test_s:string'])
89
100
  end
90
101
 
91
102
  it 'should restrict by dynamic integer field with less than restriction' do
92
103
  @search.query.dynamic_query(:custom_integer).add_restriction(:test, :less_than, 1)
93
- @connection.should_receive(:query).with(anything, hash_including(:filter_queries => ['custom_integer\:test_i:[* TO 1]']))
104
+ @search.execute!
105
+ @connection.should have_last_search_with(:fq => ['custom_integer\:test_i:[* TO 1]'])
94
106
  end
95
107
 
96
108
  it 'should restrict by dynamic float field with between restriction' do
97
109
  @search.query.dynamic_query(:custom_float).add_restriction(:test, :between, 2.2..3.3)
98
- @connection.should_receive(:query).with(anything, hash_including(:filter_queries => ['custom_float\:test_fm:[2\.2 TO 3\.3]']))
110
+ @search.execute!
111
+ @connection.should have_last_search_with(:fq => ['custom_float\:test_fm:[2\.2 TO 3\.3]'])
99
112
  end
100
113
 
101
114
  it 'should restrict by dynamic time field with any of restriction' do
102
- @search.query.dynamic_query(:custom_time).add_restriction(:test, :any_of,
103
- [Time.parse('2009-02-10 14:00:00 UTC'),
104
- Time.parse('2009-02-13 18:00:00 UTC')])
105
- @connection.should_receive(:query).with(anything, hash_including(:filter_queries => ['custom_time\:test_d:(2009\-02\-10T14\:00\:00Z OR 2009\-02\-13T18\:00\:00Z)']))
115
+ @search.query.dynamic_query(:custom_time).add_restriction(
116
+ :test,
117
+ :any_of,
118
+ [Time.parse('2009-02-10 14:00:00 UTC'),
119
+ Time.parse('2009-02-13 18:00:00 UTC')]
120
+ )
121
+ @search.execute!
122
+ @connection.should have_last_search_with(
123
+ :fq => ['custom_time\:test_d:(2009\-02\-10T14\:00\:00Z OR 2009\-02\-13T18\:00\:00Z)']
124
+ )
106
125
  end
107
126
 
108
127
  it 'should restrict by dynamic boolean field with equality restriction' do
109
128
  @search.query.dynamic_query(:custom_boolean).add_restriction(:test, :equal_to, false)
110
- @connection.should_receive(:query).with(anything, hash_including(:filter_queries => ['custom_boolean\:test_b:false']))
129
+ @search.execute!
130
+ @connection.should have_last_search_with(:fq => ['custom_boolean\:test_b:false'])
111
131
  end
112
132
 
113
133
  it 'should negate a dynamic field restriction' do
114
134
  @search.query.dynamic_query(:custom_string).add_negated_restriction(:test, :equal_to, 'foo')
115
- @connection.should_receive(:query).with(anything, hash_including(:filter_queries => ['-custom_string\:test_s:foo']))
135
+ @search.execute!
136
+ @connection.should have_last_search_with(:fq => ['-custom_string\:test_s:foo'])
116
137
  end
117
138
 
118
139
  it 'should order by a dynamic field' do
119
140
  @search.query.dynamic_query(:custom_integer).order_by(:test, :desc)
120
- @connection.should_receive(:query).with(anything, hash_including(:sort => [{ :"custom_integer:test_i" => :descending }]))
141
+ @search.execute!
142
+ @connection.should have_last_search_with(:sort => 'custom_integer:test_i desc')
121
143
  end
122
144
 
123
145
  it 'should order by a dynamic field and static field, with given precedence' do
124
146
  @search.query.dynamic_query(:custom_integer).order_by(:test, :desc)
125
147
  @search.query.order_by(:sort_title, :asc)
126
- @connection.should_receive(:query).with(anything, hash_including(:sort => [{ :"custom_integer:test_i" => :descending },
127
- { :sort_title_s => :ascending}]))
148
+ @search.execute!
149
+ @connection.should have_last_search_with(
150
+ :sort => 'custom_integer:test_i desc, sort_title_s asc'
151
+ )
128
152
  end
129
153
  end