UnderpantsGnome-sunspot 0.9.1.1
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/History.txt +39 -0
- data/LICENSE +18 -0
- data/README.rdoc +154 -0
- data/Rakefile +9 -0
- data/TODO +4 -0
- data/VERSION.yml +4 -0
- data/bin/sunspot-configure-solr +46 -0
- data/bin/sunspot-solr +62 -0
- data/lib/light_config.rb +40 -0
- data/lib/sunspot.rb +470 -0
- data/lib/sunspot/adapters.rb +265 -0
- data/lib/sunspot/composite_setup.rb +186 -0
- data/lib/sunspot/configuration.rb +38 -0
- data/lib/sunspot/data_extractor.rb +47 -0
- data/lib/sunspot/date_facet.rb +36 -0
- data/lib/sunspot/date_facet_row.rb +17 -0
- data/lib/sunspot/dsl.rb +3 -0
- data/lib/sunspot/dsl/field_query.rb +72 -0
- data/lib/sunspot/dsl/fields.rb +86 -0
- data/lib/sunspot/dsl/query.rb +59 -0
- data/lib/sunspot/dsl/query_facet.rb +31 -0
- data/lib/sunspot/dsl/restriction.rb +25 -0
- data/lib/sunspot/dsl/scope.rb +193 -0
- data/lib/sunspot/dsl/search.rb +30 -0
- data/lib/sunspot/facet.rb +51 -0
- data/lib/sunspot/facet_row.rb +34 -0
- data/lib/sunspot/field.rb +157 -0
- data/lib/sunspot/field_factory.rb +126 -0
- data/lib/sunspot/indexer.rb +127 -0
- data/lib/sunspot/instantiated_facet.rb +38 -0
- data/lib/sunspot/instantiated_facet_row.rb +12 -0
- data/lib/sunspot/query.rb +190 -0
- data/lib/sunspot/query/base_query.rb +90 -0
- data/lib/sunspot/query/connective.rb +77 -0
- data/lib/sunspot/query/dynamic_query.rb +69 -0
- data/lib/sunspot/query/field_facet.rb +149 -0
- data/lib/sunspot/query/field_query.rb +57 -0
- data/lib/sunspot/query/pagination.rb +39 -0
- data/lib/sunspot/query/query_facet.rb +72 -0
- data/lib/sunspot/query/query_facet_row.rb +19 -0
- data/lib/sunspot/query/restriction.rb +225 -0
- data/lib/sunspot/query/scope.rb +165 -0
- data/lib/sunspot/query/sort.rb +36 -0
- data/lib/sunspot/query/sort_composite.rb +33 -0
- data/lib/sunspot/query_facet.rb +33 -0
- data/lib/sunspot/query_facet_row.rb +21 -0
- data/lib/sunspot/schema.rb +165 -0
- data/lib/sunspot/search.rb +222 -0
- data/lib/sunspot/search/hit.rb +62 -0
- data/lib/sunspot/session.rb +201 -0
- data/lib/sunspot/setup.rb +271 -0
- data/lib/sunspot/type.rb +200 -0
- data/lib/sunspot/util.rb +164 -0
- data/solr/etc/jetty.xml +212 -0
- data/solr/etc/webdefault.xml +379 -0
- data/solr/lib/jetty-6.1.3.jar +0 -0
- data/solr/lib/jetty-util-6.1.3.jar +0 -0
- data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
- data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
- data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
- data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
- data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
- data/solr/solr/conf/elevate.xml +36 -0
- data/solr/solr/conf/protwords.txt +21 -0
- data/solr/solr/conf/schema.xml +50 -0
- data/solr/solr/conf/solrconfig.xml +696 -0
- data/solr/solr/conf/stopwords.txt +57 -0
- data/solr/solr/conf/synonyms.txt +31 -0
- data/solr/start.jar +0 -0
- data/solr/webapps/solr.war +0 -0
- data/spec/api/adapters_spec.rb +33 -0
- data/spec/api/build_search_spec.rb +918 -0
- data/spec/api/indexer_spec.rb +311 -0
- data/spec/api/query_spec.rb +153 -0
- data/spec/api/search_retrieval_spec.rb +325 -0
- data/spec/api/session_spec.rb +157 -0
- data/spec/api/spec_helper.rb +1 -0
- data/spec/api/sunspot_spec.rb +18 -0
- data/spec/integration/dynamic_fields_spec.rb +55 -0
- data/spec/integration/faceting_spec.rb +169 -0
- data/spec/integration/keyword_search_spec.rb +83 -0
- data/spec/integration/scoped_search_spec.rb +188 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/integration/stored_fields_spec.rb +10 -0
- data/spec/integration/test_pagination.rb +32 -0
- data/spec/mocks/adapters.rb +32 -0
- data/spec/mocks/blog.rb +3 -0
- data/spec/mocks/comment.rb +19 -0
- data/spec/mocks/connection.rb +84 -0
- data/spec/mocks/mock_adapter.rb +30 -0
- data/spec/mocks/mock_record.rb +41 -0
- data/spec/mocks/photo.rb +8 -0
- data/spec/mocks/post.rb +70 -0
- data/spec/mocks/user.rb +8 -0
- data/spec/spec_helper.rb +47 -0
- data/tasks/gemspec.rake +25 -0
- data/tasks/rcov.rake +28 -0
- data/tasks/rdoc.rake +21 -0
- data/tasks/schema.rake +19 -0
- data/tasks/spec.rake +24 -0
- data/tasks/todo.rake +4 -0
- data/templates/schema.xml.haml +24 -0
- metadata +245 -0
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Sunspot do
|
4
|
+
describe "reset!" do
|
5
|
+
it "should reset current session" do
|
6
|
+
old_session = Sunspot.send(:session)
|
7
|
+
Sunspot.reset!(true)
|
8
|
+
Sunspot.send(:session).should_not == old_session
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should keep keep configuration if specified" do
|
12
|
+
Sunspot.config.solr.url = "http://localhost:9999/path/solr"
|
13
|
+
config_before_reset = Sunspot.config
|
14
|
+
Sunspot.reset!(true)
|
15
|
+
Sunspot.config.should == config_before_reset
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
describe 'dynamic fields' do
|
2
|
+
before :each do
|
3
|
+
Sunspot.remove_all
|
4
|
+
@posts = Post.new(:custom_string => { :cuisine => 'Pizza' }),
|
5
|
+
Post.new(:custom_string => { :cuisine => 'Greek' }),
|
6
|
+
Post.new(:custom_string => { :cuisine => 'Greek' })
|
7
|
+
Sunspot.index!(@posts)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should search for dynamic string field' do
|
11
|
+
Sunspot.search(Post) do
|
12
|
+
dynamic(:custom_string) do
|
13
|
+
with(:cuisine, 'Pizza')
|
14
|
+
end
|
15
|
+
end.results.should == [@posts.first]
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'faceting' do
|
19
|
+
before :each do
|
20
|
+
@search = Sunspot.search(Post) do
|
21
|
+
dynamic :custom_string do
|
22
|
+
facet :cuisine
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should return value "value" with count 2' do
|
28
|
+
row = @search.dynamic_facet(:custom_string, :cuisine).rows[0]
|
29
|
+
row.value.should == 'Greek'
|
30
|
+
row.count.should == 2
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should return value "other" with count 1' do
|
34
|
+
row = @search.dynamic_facet(:custom_string, :cuisine).rows[1]
|
35
|
+
row.value.should == 'Pizza'
|
36
|
+
row.count.should == 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should order by dynamic string field ascending' do
|
41
|
+
Sunspot.search(Post) do
|
42
|
+
dynamic :custom_string do
|
43
|
+
order_by :cuisine, :asc
|
44
|
+
end
|
45
|
+
end.results.last.should == @posts.first
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should order by dynamic string field descending' do
|
49
|
+
Sunspot.search(Post) do
|
50
|
+
dynamic :custom_string do
|
51
|
+
order_by :cuisine, :desc
|
52
|
+
end
|
53
|
+
end.results.first.should == @posts.first
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'search faceting' do
|
4
|
+
def self.test_field_type(name, attribute, field, value1, value2)
|
5
|
+
context "with field of type #{name}" do
|
6
|
+
before :all do
|
7
|
+
Sunspot.remove_all
|
8
|
+
2.times do
|
9
|
+
Sunspot.index(Post.new(attribute => value1))
|
10
|
+
end
|
11
|
+
Sunspot.index(Post.new(attribute => value2))
|
12
|
+
Sunspot.commit
|
13
|
+
end
|
14
|
+
|
15
|
+
before :each do
|
16
|
+
@search = Sunspot.search(Post) do
|
17
|
+
facet(field)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return value #{value1.inspect} with count 2" do
|
22
|
+
row = @search.facet(field).rows[0]
|
23
|
+
row.value.should == value1
|
24
|
+
row.count.should == 2
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return value #{value2.inspect} with count 1" do
|
28
|
+
row = @search.facet(field).rows[1]
|
29
|
+
row.value.should == value2
|
30
|
+
row.count.should == 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
test_field_type('String', :title, :title, 'Title 1', 'Title 2')
|
36
|
+
test_field_type('Integer', :blog_id, :blog_id, 3, 4)
|
37
|
+
test_field_type('Float', :ratings_average, :average_rating, 2.2, 1.1)
|
38
|
+
test_field_type('Time', :published_at, :published_at, Time.mktime(2008, 02, 17, 17, 45, 04),
|
39
|
+
Time.mktime(2008, 07, 02, 03, 56, 22))
|
40
|
+
test_field_type('Boolean', :featured, :featured, true, false)
|
41
|
+
|
42
|
+
context 'facet options' do
|
43
|
+
before :all do
|
44
|
+
Sunspot.remove_all
|
45
|
+
facet_values = %w(zero one two three four)
|
46
|
+
facet_values.each_with_index do |value, i|
|
47
|
+
i.times { Sunspot.index(Post.new(:title => value, :blog_id => 1)) }
|
48
|
+
end
|
49
|
+
Sunspot.index(Post.new(:title => 'zero', :blog_id => 2))
|
50
|
+
Sunspot.commit
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should limit the number of facet rows' do
|
54
|
+
search = Sunspot.search(Post) do
|
55
|
+
facet :title, :limit => 3
|
56
|
+
end
|
57
|
+
search.facet(:title).should have(3).rows
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should not return zeros by default' do
|
61
|
+
search = Sunspot.search(Post) do
|
62
|
+
with :blog_id, 1
|
63
|
+
facet :title
|
64
|
+
end
|
65
|
+
search.facet(:title).rows.map { |row| row.value }.should_not include('zero')
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should return zeros when specified' do
|
69
|
+
search = Sunspot.search(Post) do
|
70
|
+
with :blog_id, 1
|
71
|
+
facet :title, :zeros => true
|
72
|
+
end
|
73
|
+
search.facet(:title).rows.map { |row| row.value }.should include('zero')
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should return a specified minimum count' do
|
77
|
+
search = Sunspot.search(Post) do
|
78
|
+
with :blog_id, 1
|
79
|
+
facet :title, :minimum_count => 2
|
80
|
+
end
|
81
|
+
search.facet(:title).rows.map { |row| row.value }.should == %w(four three two)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should order facets lexically' do
|
85
|
+
search = Sunspot.search(Post) do
|
86
|
+
with :blog_id, 1
|
87
|
+
facet :title, :sort => :index
|
88
|
+
end
|
89
|
+
search.facet(:title).rows.map { |row| row.value }.should == %w(four one three two)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should order facets by count' do
|
93
|
+
search = Sunspot.search(Post) do
|
94
|
+
with :blog_id, 1
|
95
|
+
facet :title, :sort => :count
|
96
|
+
end
|
97
|
+
search.facet(:title).rows.map { |row| row.value }.should == %w(four three two one)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'date facets' do
|
102
|
+
before :all do
|
103
|
+
Sunspot.remove_all
|
104
|
+
time = Time.utc(2009, 7, 8)
|
105
|
+
Sunspot.index!(
|
106
|
+
(0..2).map { |i| Post.new(:published_at => time + i*60*60*16) }
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should return time ranges' do
|
111
|
+
time = Time.utc(2009, 7, 8)
|
112
|
+
search = Sunspot.search(Post) do
|
113
|
+
facet :published_at, :time_range => time..(time + 60*60*24*2), :sort => :count
|
114
|
+
end
|
115
|
+
search.facet(:published_at).rows.first.value.should == (time..(time + 60*60*24))
|
116
|
+
search.facet(:published_at).rows.first.count.should == 2
|
117
|
+
search.facet(:published_at).rows.last.value.should == ((time + 60*60*24)..(time + 60*60*24*2))
|
118
|
+
search.facet(:published_at).rows.last.count.should == 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'class facets' do
|
123
|
+
before :all do
|
124
|
+
Sunspot.remove_all
|
125
|
+
Sunspot.index!(Post.new, Post.new, Namespaced::Comment.new)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should return classes' do
|
129
|
+
search = Sunspot.search(Post, Namespaced::Comment) do
|
130
|
+
facet(:class, :sort => :count)
|
131
|
+
end
|
132
|
+
search.facet(:class).rows.first.value.should == Post
|
133
|
+
search.facet(:class).rows.first.count.should == 2
|
134
|
+
search.facet(:class).rows.last.value.should == Namespaced::Comment
|
135
|
+
search.facet(:class).rows.last.count.should == 1
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'query facets' do
|
140
|
+
before :all do
|
141
|
+
Sunspot.remove_all
|
142
|
+
Sunspot.index!(
|
143
|
+
[1.1, 1.2, 3.2, 3.4, 3.9, 4.1].map do |rating|
|
144
|
+
Post.new(:ratings_average => rating)
|
145
|
+
end
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should return specified facets' do
|
150
|
+
search = Sunspot.search(Post) do
|
151
|
+
facet :rating_range do
|
152
|
+
for rating in [1.0, 2.0, 3.0, 4.0]
|
153
|
+
range = rating..(rating + 1.0)
|
154
|
+
row range do
|
155
|
+
with :average_rating, rating..(rating + 1.0)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
facet = search.facet(:rating_range)
|
161
|
+
facet.rows[0].value.should == (3.0..4.0)
|
162
|
+
facet.rows[0].count.should == 3
|
163
|
+
facet.rows[1].value.should == (1.0..2.0)
|
164
|
+
facet.rows[1].count.should == 2
|
165
|
+
facet.rows[2].value.should == (4.0..5.0)
|
166
|
+
facet.rows[2].count.should == 1
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
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 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
|
+
end
|
51
|
+
|
52
|
+
describe 'with field boost' do
|
53
|
+
before :all do
|
54
|
+
Sunspot.remove_all
|
55
|
+
@posts = [:title, :body].map { |field| Post.new(field => 'rhinoceros') }
|
56
|
+
Sunspot.index!(*@posts)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should assign a higher score to the result matching the higher-boosted field' do
|
60
|
+
search = Sunspot.search(Post) { keywords 'rhinoceros' }
|
61
|
+
search.hits.map { |hit| hit.primary_key }.should ==
|
62
|
+
@posts.map { |post| post.id.to_s }
|
63
|
+
search.hits.first.score.should > search.hits.last.score
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'with document boost' do
|
68
|
+
before :all do
|
69
|
+
Sunspot.remove_all
|
70
|
+
@posts = [4.0, 2.0].map do |rating|
|
71
|
+
Post.new(:title => 'Test', :ratings_average => rating)
|
72
|
+
end
|
73
|
+
Sunspot.index!(*@posts)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should assign a higher score to the higher-boosted document' do
|
77
|
+
search = Sunspot.search(Post) { keywords 'test' }
|
78
|
+
search.hits.map { |hit| hit.primary_key }.should ==
|
79
|
+
@posts.map { |post| post.id.to_s }
|
80
|
+
search.hits.first.score.should > search.hits.last.score
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'scoped_search' do
|
4
|
+
def self.test_field_type(name, attribute, field, *values)
|
5
|
+
raise(ArgumentError, 'Please supply five values') unless values.length == 5
|
6
|
+
|
7
|
+
context "with field of type #{name}" do
|
8
|
+
before :all do
|
9
|
+
Sunspot.remove_all
|
10
|
+
@posts = values.map do |value|
|
11
|
+
post = Post.new(attribute => value)
|
12
|
+
Sunspot.index(post)
|
13
|
+
post
|
14
|
+
end
|
15
|
+
Sunspot.commit
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should filter by exact match' do
|
19
|
+
Sunspot.search(Post) { with(field, values[2]) }.results.should == [@posts[2]]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should reject by inexact match' do
|
23
|
+
results = Sunspot.search(Post) { without(field, values[2]) }.results
|
24
|
+
[0, 1, 3, 4].each { |i| results.should include(@posts[i]) }
|
25
|
+
results.should_not include(@posts[2])
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should filter by less than' do
|
29
|
+
results = Sunspot.search(Post) { with(field).less_than values[2] }.results
|
30
|
+
(0..2).each { |i| results.should include(@posts[i]) }
|
31
|
+
(3..4).each { |i| results.should_not include(@posts[i]) }
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should reject by less than' do
|
35
|
+
results = Sunspot.search(Post) { without(field).less_than values[2] }.results
|
36
|
+
(0..2).each { |i| results.should_not include(@posts[i]) }
|
37
|
+
(3..4).each { |i| results.should include(@posts[i]) }
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should filter by greater than' do
|
41
|
+
results = Sunspot.search(Post) { with(field).greater_than values[2] }.results
|
42
|
+
(2..4).each { |i| results.should include(@posts[i]) }
|
43
|
+
(0..1).each { |i| results.should_not include(@posts[i]) }
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should reject by greater than' do
|
47
|
+
results = Sunspot.search(Post) { without(field).greater_than values[2] }.results
|
48
|
+
(2..4).each { |i| results.should_not include(@posts[i]) }
|
49
|
+
(0..1).each { |i| results.should include(@posts[i]) }
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should filter by between' do
|
53
|
+
results = Sunspot.search(Post) { with(field).between(values[1]..values[3]) }.results
|
54
|
+
(1..3).each { |i| results.should include(@posts[i]) }
|
55
|
+
[0, 4].each { |i| results.should_not include(@posts[i]) }
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should reject by between' do
|
59
|
+
results = Sunspot.search(Post) { without(field).between(values[1]..values[3]) }.results
|
60
|
+
(1..3).each { |i| results.should_not include(@posts[i]) }
|
61
|
+
[0, 4].each { |i| results.should include(@posts[i]) }
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should filter by any of' do
|
65
|
+
results = Sunspot.search(Post) { with(field).any_of(values.values_at(1, 3)) }.results
|
66
|
+
[1, 3].each { |i| results.should include(@posts[i]) }
|
67
|
+
[0, 2, 4].each { |i| results.should_not include(@posts[i]) }
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should reject by any of' do
|
71
|
+
results = Sunspot.search(Post) { without(field).any_of(values.values_at(1, 3)) }.results
|
72
|
+
[1, 3].each { |i| results.should_not include(@posts[i]) }
|
73
|
+
[0, 2, 4].each { |i| results.should include(@posts[i]) }
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should order by field ascending' do
|
77
|
+
results = Sunspot.search(Post) { order_by field, :asc }.results
|
78
|
+
results.should == @posts
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should order by field descending' do
|
82
|
+
results = Sunspot.search(Post) { order_by field, :desc }.results
|
83
|
+
results.should == @posts.reverse
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
test_field_type 'String', :title, :title, 'apple', 'banana', 'cherry', 'date', 'eggplant'
|
89
|
+
test_field_type 'Integer', :blog_id, :blog_id, -2, 0, 3, 12, 20
|
90
|
+
test_field_type 'Float', :ratings_average, :average_rating, -2.5, 0.0, 3.2, 3.5, 16.0
|
91
|
+
test_field_type 'Time', :published_at, :published_at, *(['1970-01-01 00:00:00 UTC', '1983-07-08 04:00:00 UTC', '1983-07-08 02:00:00 -0500',
|
92
|
+
'2005-11-05 10:00:00 UTC', Time.now.to_s].map { |t| Time.parse(t) })
|
93
|
+
|
94
|
+
describe 'Boolean field type' do
|
95
|
+
before :all do
|
96
|
+
Sunspot.remove_all
|
97
|
+
@posts = [Post.new(:featured => true), Post.new(:featured => false), Post.new]
|
98
|
+
Sunspot.index!(@posts)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should filter by exact match for true' do
|
102
|
+
Sunspot.search(Post) { with(:featured, true) }.results.should == [@posts[0]]
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should filter for exact match for false' do
|
106
|
+
Sunspot.search(Post) { with(:featured, false) }.results.should == [@posts[1]]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'passing nil value to equal' do
|
111
|
+
before :all do
|
112
|
+
Sunspot.remove_all
|
113
|
+
@posts = [Post.new(:title => 'apple'), Post.new]
|
114
|
+
Sunspot.index!(@posts)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should filter results without value for field' do
|
118
|
+
Sunspot.search(Post) { with(:title, nil) }.results.should == [@posts[1]]
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should exclude results without value for field' do
|
122
|
+
Sunspot.search(Post) { without(:title, nil) }.results.should == [@posts[0]]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe 'exclusion by identity' do
|
127
|
+
before do
|
128
|
+
@posts = (1..5).map do |i|
|
129
|
+
post = Post.new
|
130
|
+
Sunspot.index(post)
|
131
|
+
post
|
132
|
+
end
|
133
|
+
Sunspot.commit
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should not return excluded object' do
|
137
|
+
excluded_post = @posts.shift
|
138
|
+
Sunspot.search(Post) { without(excluded_post) }.results.should_not include(excluded_post)
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'should return objects not excluded' do
|
142
|
+
excluded_post = @posts.shift
|
143
|
+
for included_post in @posts
|
144
|
+
Sunspot.search(Post) { without(excluded_post) }.results.should include(included_post)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should not return excluded objects' do
|
149
|
+
excluded_posts = [@posts.shift, @posts.shift]
|
150
|
+
for excluded_post in excluded_posts
|
151
|
+
Sunspot.search(Post) { without(excluded_posts) }.results.should_not include(excluded_post)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe 'multiple column ordering' do
|
157
|
+
before do
|
158
|
+
Sunspot.remove_all
|
159
|
+
@posts = [
|
160
|
+
Post.new(:ratings_average => 2, :title => 'banana'),
|
161
|
+
Post.new(:ratings_average => 2, :title => 'eggplant'),
|
162
|
+
Post.new(:ratings_average => 1, :title => 'apple')
|
163
|
+
].each { |post| Sunspot.index(post) }
|
164
|
+
Sunspot.commit
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'should order with precedence given' do
|
168
|
+
search = Sunspot.search(Post) do
|
169
|
+
order_by :average_rating, :desc
|
170
|
+
order_by :sort_title, :asc
|
171
|
+
end
|
172
|
+
search.results.should == @posts
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe 'ordering by random' do
|
177
|
+
it 'should order randomly (run this test again if it fails)' do
|
178
|
+
Sunspot.remove_all
|
179
|
+
Sunspot.index!(Array.new(100) { Post.new })
|
180
|
+
result_sets = Array.new(2) do
|
181
|
+
Sunspot.search(Post) { order_by_random }.results.map do |result|
|
182
|
+
result.id
|
183
|
+
end
|
184
|
+
end
|
185
|
+
result_sets[0].should_not == result_sets[1]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|