sunspot 2.1.1 → 2.2.0
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.
- data/lib/sunspot.rb +13 -9
- data/lib/sunspot/dsl.rb +4 -3
- data/lib/sunspot/dsl/fields.rb +11 -16
- data/lib/sunspot/dsl/paginatable.rb +4 -1
- data/lib/sunspot/dsl/spellcheckable.rb +14 -0
- data/lib/sunspot/dsl/standard_query.rb +63 -35
- data/lib/sunspot/field.rb +54 -8
- data/lib/sunspot/field_factory.rb +2 -4
- data/lib/sunspot/indexer.rb +1 -2
- data/lib/sunspot/query.rb +2 -2
- data/lib/sunspot/query/abstract_fulltext.rb +69 -0
- data/lib/sunspot/query/common_query.rb +13 -2
- data/lib/sunspot/query/composite_fulltext.rb +58 -8
- data/lib/sunspot/query/dismax.rb +14 -67
- data/lib/sunspot/query/function_query.rb +1 -2
- data/lib/sunspot/query/geo.rb +1 -1
- data/lib/sunspot/query/join.rb +90 -0
- data/lib/sunspot/query/pagination.rb +12 -4
- data/lib/sunspot/query/restriction.rb +3 -4
- data/lib/sunspot/query/sort.rb +6 -0
- data/lib/sunspot/query/sort_composite.rb +7 -0
- data/lib/sunspot/query/spellcheck.rb +19 -0
- data/lib/sunspot/query/standard_query.rb +24 -2
- data/lib/sunspot/query/text_field_boost.rb +1 -3
- data/lib/sunspot/search/abstract_search.rb +10 -1
- data/lib/sunspot/search/cursor_paginated_collection.rb +32 -0
- data/lib/sunspot/search/paginated_collection.rb +1 -0
- data/lib/sunspot/search/standard_search.rb +71 -3
- data/lib/sunspot/session.rb +6 -6
- data/lib/sunspot/setup.rb +6 -1
- data/lib/sunspot/util.rb +46 -13
- data/lib/sunspot/version.rb +1 -1
- data/spec/api/query/fulltext_examples.rb +150 -1
- data/spec/api/query/geo_examples.rb +2 -6
- data/spec/api/query/join_spec.rb +3 -3
- data/spec/api/query/ordering_pagination_examples.rb +14 -0
- data/spec/api/query/spellcheck_examples.rb +20 -0
- data/spec/api/query/standard_spec.rb +1 -0
- data/spec/api/search/cursor_paginated_collection_spec.rb +35 -0
- data/spec/api/search/paginated_collection_spec.rb +1 -0
- data/spec/api/session_spec.rb +36 -2
- data/spec/integration/spellcheck_spec.rb +74 -0
- data/spec/mocks/connection.rb +5 -3
- data/spec/mocks/photo.rb +12 -4
- data/spec/spec_helper.rb +4 -0
- metadata +24 -5
- checksums.yaml +0 -7
data/lib/sunspot/version.rb
CHANGED
@@ -188,7 +188,8 @@ shared_examples_for 'fulltext query' do
|
|
188
188
|
search Photo do
|
189
189
|
keywords 'great pizza'
|
190
190
|
end
|
191
|
-
|
191
|
+
# Hashes in 1.8 aren't ordered
|
192
|
+
connection.searches.last[:qf].split(" ").sort.join(" ").should eq 'caption_text^1.5 description_text'
|
192
193
|
end
|
193
194
|
|
194
195
|
it 'sets default boost with fields specified in options' do
|
@@ -310,4 +311,152 @@ shared_examples_for 'fulltext query' do
|
|
310
311
|
end
|
311
312
|
end.should raise_error(Sunspot::UnrecognizedFieldError)
|
312
313
|
end
|
314
|
+
|
315
|
+
describe 'connective examples' do
|
316
|
+
it 'creates a disjunction between two subqueries' do
|
317
|
+
search Post do
|
318
|
+
any do
|
319
|
+
fulltext 'keywords1', :fields => :title
|
320
|
+
fulltext 'keyword2', :fields => :body
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
connection.searches.last[:q].should eq "(_query_:\"{!edismax qf='title_text'}keywords1\" OR _query_:\"{!edismax qf='body_textsv'}keyword2\")"
|
325
|
+
end
|
326
|
+
|
327
|
+
it 'creates a conjunction inside of a disjunction' do
|
328
|
+
search do
|
329
|
+
any do
|
330
|
+
fulltext 'keywords1', :fields => :body
|
331
|
+
|
332
|
+
all do
|
333
|
+
fulltext 'keyword2', :fields => :body
|
334
|
+
fulltext 'keyword3', :fields => :body
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
connection.searches.last[:q].should eq "(_query_:\"{!edismax qf='body_textsv'}keywords1\" OR (_query_:\"{!edismax qf='body_textsv'}keyword2\" AND _query_:\"{!edismax qf='body_textsv'}keyword3\"))"
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'does nothing special if #all/#any called from the top level or called multiple times' do
|
343
|
+
search Post do
|
344
|
+
all do
|
345
|
+
fulltext 'keywords1', :fields => :title
|
346
|
+
fulltext 'keyword2', :fields => :body
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
connection.searches.last[:q].should eq "(_query_:\"{!edismax qf='title_text'}keywords1\" AND _query_:\"{!edismax qf='body_textsv'}keyword2\")"
|
351
|
+
end
|
352
|
+
|
353
|
+
it 'does nothing special if #all/#any are mixed and called multiple times' do
|
354
|
+
search Post do
|
355
|
+
all do
|
356
|
+
any do
|
357
|
+
all do
|
358
|
+
fulltext 'keywords1', :fields => :title
|
359
|
+
fulltext 'keyword2', :fields => :body
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
connection.searches.last[:q].should eq "(_query_:\"{!edismax qf='title_text'}keywords1\" AND _query_:\"{!edismax qf='body_textsv'}keyword2\")"
|
366
|
+
|
367
|
+
search Post do
|
368
|
+
any do
|
369
|
+
all do
|
370
|
+
any do
|
371
|
+
fulltext 'keywords1', :fields => :title
|
372
|
+
fulltext 'keyword2', :fields => :body
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
connection.searches.last[:q].should eq "(_query_:\"{!edismax qf='title_text'}keywords1\" OR _query_:\"{!edismax qf='body_textsv'}keyword2\")"
|
379
|
+
end
|
380
|
+
|
381
|
+
it "does not add empty parentheses" do
|
382
|
+
search Post do
|
383
|
+
any do
|
384
|
+
all do
|
385
|
+
end
|
386
|
+
|
387
|
+
any do
|
388
|
+
fulltext 'keywords1', :fields => :title
|
389
|
+
all do
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
connection.searches.last[:q].should eq "_query_:\"{!edismax qf='title_text'}keywords1\""
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
describe "joins" do
|
400
|
+
it "should search by join" do
|
401
|
+
srch = search PhotoContainer do
|
402
|
+
any do
|
403
|
+
fulltext 'keyword1', :fields => :caption
|
404
|
+
fulltext 'keyword2', :fields => :description
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
obj_id = find_ob_id(srch)
|
409
|
+
q_name = "qPhoto#{obj_id}"
|
410
|
+
fq_name = "f#{q_name}"
|
411
|
+
|
412
|
+
connection.searches.last[:q].should eq "(_query_:\"{!join from=photo_container_id_i to=id_i v=$#{q_name} fq=$#{fq_name}}\" OR _query_:\"{!edismax qf='description_text^1.2'}keyword2\")"
|
413
|
+
connection.searches.last[q_name].should eq "_query_:\"{!edismax qf='caption_text'}keyword1\""
|
414
|
+
connection.searches.last[fq_name].should eq "type:Photo"
|
415
|
+
end
|
416
|
+
|
417
|
+
it "should be able to resolve name conflicts with the :prefix option" do
|
418
|
+
srch = search PhotoContainer do
|
419
|
+
any do
|
420
|
+
fulltext 'keyword1', :fields => :description
|
421
|
+
fulltext 'keyword2', :fields => :photo_description
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
obj_id = find_ob_id(srch)
|
426
|
+
q_name = "qPhoto#{obj_id}"
|
427
|
+
fq_name = "f#{q_name}"
|
428
|
+
|
429
|
+
connection.searches.last[:q].should eq "(_query_:\"{!edismax qf='description_text^1.2'}keyword1\" OR _query_:\"{!join from=photo_container_id_i to=id_i v=$#{q_name} fq=$#{fq_name}}\")"
|
430
|
+
connection.searches.last[q_name].should eq "_query_:\"{!edismax qf='description_text'}keyword2\""
|
431
|
+
connection.searches.last[fq_name].should eq "type:Photo"
|
432
|
+
end
|
433
|
+
|
434
|
+
it "should recognize fields when adding from DSL, e.g. when calling boost_fields" do
|
435
|
+
srch = search PhotoContainer do
|
436
|
+
any do
|
437
|
+
fulltext 'keyword1', :fields => [:photo_description, :description] do
|
438
|
+
boost_fields(:photo_description => 1.3, :description => 1.5)
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
obj_id = find_ob_id(srch)
|
444
|
+
q_name = "qPhoto#{obj_id}"
|
445
|
+
fq_name = "f#{q_name}"
|
446
|
+
|
447
|
+
connection.searches.last[:q].should eq "(_query_:\"{!edismax qf='description_text^1.5'}keyword1\" OR _query_:\"{!join from=photo_container_id_i to=id_i v=$#{q_name} fq=$#{fq_name}}\")"
|
448
|
+
connection.searches.last[q_name].should eq "_query_:\"{!edismax qf='description_text^1.3'}keyword1\""
|
449
|
+
connection.searches.last[fq_name].should eq "type:Photo"
|
450
|
+
end
|
451
|
+
|
452
|
+
private
|
453
|
+
|
454
|
+
def find_ob_id(search)
|
455
|
+
search.query.
|
456
|
+
instance_variable_get("@components").find { |c| c.is_a?(Sunspot::Query::Conjunction) }.
|
457
|
+
instance_variable_get("@components").find { |c| c.is_a?(Sunspot::Query::Disjunction) }.
|
458
|
+
instance_variable_get("@components").find { |c| c.is_a?(Sunspot::Query::Join) }.
|
459
|
+
object_id
|
460
|
+
end
|
461
|
+
end
|
313
462
|
end
|
@@ -41,12 +41,8 @@ shared_examples_for 'geohash query' do
|
|
41
41
|
fulltext 'pizza', :fields => :title
|
42
42
|
with(:coordinates).near(40.7, -73.5)
|
43
43
|
end
|
44
|
-
expected =
|
45
|
-
|
46
|
-
connection.should have_last_search_including(
|
47
|
-
:q,
|
48
|
-
%Q(_query_:"{!edismax qf='title_text'}pizza" (#{build_geo_query}))
|
49
|
-
)
|
44
|
+
expected = %Q((_query_:"{!edismax qf='title_text'}pizza" AND (#{build_geo_query})))
|
45
|
+
connection.should have_last_search_including(:q, expected)
|
50
46
|
end
|
51
47
|
|
52
48
|
private
|
data/spec/api/query/join_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe 'join' do
|
|
6
6
|
with(:caption, 'blah')
|
7
7
|
end
|
8
8
|
connection.should have_last_search_including(
|
9
|
-
:fq, "{!join from=
|
9
|
+
:fq, "{!join from=photo_container_id_i to=id_i}caption_s:blah")
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'should greater_than search by join' do
|
@@ -14,6 +14,6 @@ describe 'join' do
|
|
14
14
|
with(:photo_rating).greater_than(3)
|
15
15
|
end
|
16
16
|
connection.should have_last_search_including(
|
17
|
-
:fq, "{!join from=
|
17
|
+
:fq, "{!join from=photo_container_id_i to=id_i}average_rating_ft:{3\\.0 TO *}")
|
18
18
|
end
|
19
|
-
end
|
19
|
+
end
|
@@ -46,6 +46,20 @@ shared_examples_for 'sortable query' do
|
|
46
46
|
connection.should have_last_search_with(:rows => 15, :start => 30)
|
47
47
|
end
|
48
48
|
|
49
|
+
it 'paginates with initial cursor' do
|
50
|
+
search do
|
51
|
+
paginate :cursor => '*', :per_page => 15
|
52
|
+
end
|
53
|
+
connection.should have_last_search_with(:rows => 15, :cursorMark => '*')
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'paginates with given cursor' do
|
57
|
+
search do
|
58
|
+
paginate :cursor => 'AoIIP4AAACxQcm9maWxlIDEwMTk='
|
59
|
+
end
|
60
|
+
connection.should have_last_search_with(:cursorMark => 'AoIIP4AAACxQcm9maWxlIDEwMTk=')
|
61
|
+
end
|
62
|
+
|
49
63
|
it 'orders by a single field' do
|
50
64
|
search do
|
51
65
|
order_by :average_rating, :desc
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
shared_examples_for 'spellcheck query' do
|
4
|
+
|
5
|
+
it 'sends spellcheck parameters to solr' do
|
6
|
+
search do
|
7
|
+
spellcheck
|
8
|
+
end
|
9
|
+
connection.should have_last_search_including(:spellcheck, true)
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
it "sends additional spellcheck parameters with camel casing" do
|
14
|
+
search do
|
15
|
+
spellcheck :only_more_popular => true, :count => 5
|
16
|
+
end
|
17
|
+
connection.should have_last_search_including('spellcheck.onlyMorePopular', true)
|
18
|
+
connection.should have_last_search_including('spellcheck.count', 5)
|
19
|
+
end
|
20
|
+
end
|
@@ -13,6 +13,7 @@ describe 'standard query', :type => :query do
|
|
13
13
|
it_should_behave_like "geohash query"
|
14
14
|
it_should_behave_like "spatial query"
|
15
15
|
it_should_behave_like "stats query"
|
16
|
+
it_should_behave_like "spellcheck query"
|
16
17
|
|
17
18
|
it 'adds a no-op query to :q parameter when no :q provided' do
|
18
19
|
session.search Post do
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe "CursorPaginatedCollection" do
|
4
|
+
subject { Sunspot::Search::CursorPaginatedCollection.new [], 10, 20, '*', 'AoIIP4AAACxQcm9maWxlIDEwMTk=' }
|
5
|
+
|
6
|
+
it { subject.should be_an(Array) }
|
7
|
+
|
8
|
+
describe "#send" do
|
9
|
+
it 'should allow send' do
|
10
|
+
expect { subject.send(:current_cursor) }.to_not raise_error
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#respond_to?" do
|
15
|
+
it 'should return true for current_cursor' do
|
16
|
+
subject.respond_to?(:current_cursor).should be_true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "behaves like a WillPaginate::Collection" do
|
21
|
+
it { subject.total_entries.should eql(20) }
|
22
|
+
it { subject.total_pages.should eql(2) }
|
23
|
+
it { subject.current_cursor.should eql('*') }
|
24
|
+
it { subject.per_page.should eql(10) }
|
25
|
+
it { subject.next_page_cursor.should eql('AoIIP4AAACxQcm9maWxlIDEwMTk=') }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "behaves like Kaminari" do
|
29
|
+
it { subject.total_count.should eql(20) }
|
30
|
+
it { subject.num_pages.should eql(2) }
|
31
|
+
it { subject.limit_value.should eql(10) }
|
32
|
+
it { subject.first_page?.should be_true }
|
33
|
+
it { subject.last_page?.should be_true }
|
34
|
+
end
|
35
|
+
end
|
@@ -23,6 +23,7 @@ describe "PaginatedCollection" do
|
|
23
23
|
it { subject.current_page.should eql(1) }
|
24
24
|
it { subject.per_page.should eql(10) }
|
25
25
|
it { subject.previous_page.should be_nil }
|
26
|
+
it { subject.prev_page.should be_nil }
|
26
27
|
it { subject.next_page.should eql(2) }
|
27
28
|
it { subject.out_of_bounds?.should_not be_true }
|
28
29
|
it { subject.offset.should eql(0) }
|
data/spec/api/session_spec.rb
CHANGED
@@ -35,6 +35,26 @@ shared_examples_for 'all sessions' do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
context '#commit(bool)' do
|
39
|
+
it 'should soft-commit if bool=true' do
|
40
|
+
@session.commit(true)
|
41
|
+
connection.should have(1).commits
|
42
|
+
connection.should have(1).soft_commits
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should hard-commit if bool=false' do
|
46
|
+
@session.commit(false)
|
47
|
+
connection.should have(1).commits
|
48
|
+
connection.should have(0).soft_commits
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should hard-commit if bool is not specified' do
|
52
|
+
@session.commit
|
53
|
+
connection.should have(1).commits
|
54
|
+
connection.should have(0).soft_commits
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
38
58
|
context '#optimize()' do
|
39
59
|
before :each do
|
40
60
|
@session.optimize
|
@@ -202,17 +222,31 @@ describe 'Session' do
|
|
202
222
|
connection.should have(0).commits
|
203
223
|
end
|
204
224
|
|
205
|
-
it 'should commit when commit_if_dirty called on dirty session' do
|
225
|
+
it 'should hard commit when commit_if_dirty called on dirty session' do
|
206
226
|
@session.index(Post.new)
|
207
227
|
@session.commit_if_dirty
|
208
228
|
connection.should have(1).commits
|
209
229
|
end
|
210
230
|
|
211
|
-
it 'should commit when
|
231
|
+
it 'should soft commit when commit_if_dirty called on dirty session' do
|
232
|
+
@session.index(Post.new)
|
233
|
+
@session.commit_if_dirty(true)
|
234
|
+
connection.should have(1).commits
|
235
|
+
connection.should have(1).soft_commits
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'should hard commit when commit_if_delete_dirty called on delete_dirty session' do
|
212
239
|
@session.remove(Post.new)
|
213
240
|
@session.commit_if_delete_dirty
|
214
241
|
connection.should have(1).commits
|
215
242
|
end
|
243
|
+
|
244
|
+
it 'should soft commit when commit_if_delete_dirty called on delete_dirty session' do
|
245
|
+
@session.remove(Post.new)
|
246
|
+
@session.commit_if_delete_dirty(true)
|
247
|
+
connection.should have(1).commits
|
248
|
+
connection.should have(1).soft_commits
|
249
|
+
end
|
216
250
|
end
|
217
251
|
|
218
252
|
context 'session proxy' do
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
include SearchHelper
|
3
|
+
|
4
|
+
describe 'spellcheck' do
|
5
|
+
before :each do
|
6
|
+
Sunspot.remove_all
|
7
|
+
|
8
|
+
@posts = [
|
9
|
+
Post.new(:title => 'Clojure Developer'),
|
10
|
+
Post.new(:title => 'Conjure Flow'),
|
11
|
+
Post.new(:title => 'Clojure Analyst'),
|
12
|
+
Post.new(:title => 'C++ Developer'),
|
13
|
+
Post.new(:title => 'C++ Developing')
|
14
|
+
]
|
15
|
+
|
16
|
+
Sunspot.index!(*@posts)
|
17
|
+
Sunspot.commit
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'has no spellchecking by default' do
|
21
|
+
search = Sunspot.search(Post) do
|
22
|
+
keywords 'Closure'
|
23
|
+
end
|
24
|
+
search.spellcheck_suggestions.should == {}
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns the list of suggestions' do
|
28
|
+
search = Sunspot.search(Post) do
|
29
|
+
keywords 'Closure'
|
30
|
+
spellcheck :count => 3
|
31
|
+
end
|
32
|
+
search.spellcheck_suggestions['closure']['suggestion'].should == [
|
33
|
+
{'word'=>'clojure', 'freq'=>2}, {'word'=>'conjure', 'freq'=>1}
|
34
|
+
]
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns suggestion with highest frequency' do
|
38
|
+
search = Sunspot.search(Post) do
|
39
|
+
keywords 'Closure'
|
40
|
+
spellcheck :count => 3
|
41
|
+
end
|
42
|
+
search.spellcheck_suggestion_for('closure').should == 'clojure'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns suggestion without collation when only more popular is true' do
|
46
|
+
search = Sunspot.search(Post) do
|
47
|
+
keywords 'Closure'
|
48
|
+
spellcheck :count => 3, :only_more_popular => true, :collate => false
|
49
|
+
end
|
50
|
+
|
51
|
+
search.spellcheck_suggestion_for('closure').should == 'clojure'
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'spellcheck collation' do
|
55
|
+
it 'replaces terms that are not in the index if terms are provided' do
|
56
|
+
|
57
|
+
search = Sunspot.search(Post) do
|
58
|
+
keywords 'lojure developing'
|
59
|
+
spellcheck :count => 3, :only_more_popular => true
|
60
|
+
end
|
61
|
+
search.spellcheck_collation('lojure', 'developing').should == 'clojure developing'
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns Solr collation if terms are not provided' do
|
65
|
+
|
66
|
+
search = Sunspot.search(Post) do
|
67
|
+
keywords 'lojure developing'
|
68
|
+
spellcheck :count => 3, :only_more_popular => true
|
69
|
+
end
|
70
|
+
search.spellcheck_collation.should == 'clojure developer'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
data/spec/mocks/connection.rb
CHANGED
@@ -22,7 +22,7 @@ module Mock
|
|
22
22
|
end
|
23
23
|
|
24
24
|
class Connection
|
25
|
-
attr_reader :adds, :commits, :optims, :searches, :message, :opts, :deletes_by_query
|
25
|
+
attr_reader :adds, :commits, :soft_commits, :optims, :searches, :message, :opts, :deletes_by_query
|
26
26
|
attr_accessor :response
|
27
27
|
attr_writer :expected_handler
|
28
28
|
undef_method :select # annoyingly defined on Object
|
@@ -30,7 +30,7 @@ module Mock
|
|
30
30
|
def initialize(opts = {})
|
31
31
|
@opts = opts
|
32
32
|
@message = OpenStruct.new
|
33
|
-
@adds, @deletes, @deletes_by_query, @commits, @optims, @searches = Array.new(
|
33
|
+
@adds, @deletes, @deletes_by_query, @commits, @soft_commits, @optims, @searches = Array.new(7) { [] }
|
34
34
|
@expected_handler = :select
|
35
35
|
end
|
36
36
|
|
@@ -46,8 +46,10 @@ module Mock
|
|
46
46
|
@deletes_by_query << query
|
47
47
|
end
|
48
48
|
|
49
|
-
def commit
|
49
|
+
def commit(opts = {})
|
50
|
+
commit_attrs = opts.delete(:commit_attributes) || {}
|
50
51
|
@commits << Time.now
|
52
|
+
@soft_commits << Time.now if commit_attrs[:softCommit]
|
51
53
|
end
|
52
54
|
|
53
55
|
def optimize
|