sunspot 2.2.7 → 2.5.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.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rspec +2 -0
- data/Appraisals +7 -0
- data/Gemfile +0 -8
- data/lib/sunspot/adapters.rb +4 -1
- data/lib/sunspot/configuration.rb +1 -0
- data/lib/sunspot/data_extractor.rb +36 -6
- data/lib/sunspot/dsl/field_query.rb +11 -0
- data/lib/sunspot/dsl/field_stats.rb +7 -0
- data/lib/sunspot/dsl/fields.rb +16 -0
- data/lib/sunspot/dsl/group.rb +10 -0
- data/lib/sunspot/dsl/scope.rb +23 -18
- data/lib/sunspot/field.rb +11 -0
- data/lib/sunspot/field_factory.rb +6 -2
- data/lib/sunspot/query/abstract_json_field_facet.rb +70 -0
- data/lib/sunspot/query/bbox.rb +5 -1
- data/lib/sunspot/query/date_field_json_facet.rb +25 -0
- data/lib/sunspot/query/field_json_facet.rb +19 -0
- data/lib/sunspot/query/field_stats.rb +35 -2
- data/lib/sunspot/query/group.rb +4 -5
- data/lib/sunspot/query/join.rb +2 -4
- data/lib/sunspot/query/range_json_facet.rb +28 -0
- data/lib/sunspot/query/restriction.rb +19 -4
- data/lib/sunspot/query.rb +3 -3
- data/lib/sunspot/schema.rb +10 -2
- data/lib/sunspot/search/abstract_search.rb +14 -1
- data/lib/sunspot/search/field_json_facet.rb +33 -0
- data/lib/sunspot/search/hit.rb +6 -1
- data/lib/sunspot/search/hit_enumerable.rb +4 -1
- data/lib/sunspot/search/json_facet_row.rb +40 -0
- data/lib/sunspot/search/json_facet_stats.rb +23 -0
- data/lib/sunspot/search/standard_search.rb +2 -3
- data/lib/sunspot/search/stats_json_row.rb +82 -0
- data/lib/sunspot/search/stats_row.rb +3 -1
- data/lib/sunspot/search.rb +4 -3
- data/lib/sunspot/session.rb +13 -5
- data/lib/sunspot/setup.rb +31 -0
- data/lib/sunspot/util.rb +23 -0
- data/lib/sunspot/version.rb +1 -1
- data/spec/api/adapters_spec.rb +32 -19
- data/spec/api/batcher_spec.rb +15 -15
- data/spec/api/binding_spec.rb +3 -3
- data/spec/api/class_set_spec.rb +3 -3
- data/spec/api/data_extractor_spec.rb +39 -0
- data/spec/api/hit_enumerable_spec.rb +32 -9
- data/spec/api/indexer/attributes_spec.rb +31 -31
- data/spec/api/indexer/batch_spec.rb +8 -7
- data/spec/api/indexer/dynamic_fields_spec.rb +8 -8
- data/spec/api/indexer/fixed_fields_spec.rb +12 -12
- data/spec/api/indexer/fulltext_spec.rb +8 -8
- data/spec/api/indexer/removal_spec.rb +14 -14
- data/spec/api/indexer_spec.rb +2 -2
- data/spec/api/query/advanced_manipulation_examples.rb +3 -3
- data/spec/api/query/connectives_examples.rb +26 -14
- data/spec/api/query/dsl_spec.rb +17 -9
- data/spec/api/query/dynamic_fields_examples.rb +18 -18
- data/spec/api/query/faceting_examples.rb +62 -62
- data/spec/api/query/fulltext_examples.rb +63 -58
- data/spec/api/query/function_spec.rb +26 -26
- data/spec/api/query/geo_examples.rb +6 -6
- data/spec/api/query/group_spec.rb +6 -6
- data/spec/api/query/highlighting_examples.rb +26 -26
- data/spec/api/query/join_spec.rb +2 -2
- data/spec/api/query/more_like_this_spec.rb +29 -29
- data/spec/api/query/ordering_pagination_examples.rb +25 -25
- data/spec/api/query/scope_examples.rb +39 -39
- data/spec/api/query/spatial_examples.rb +3 -3
- data/spec/api/query/spellcheck_examples.rb +3 -3
- data/spec/api/query/standard_spec.rb +1 -1
- data/spec/api/query/stats_examples.rb +8 -8
- data/spec/api/query/text_field_scoping_examples.rb +5 -5
- data/spec/api/query/types_spec.rb +4 -4
- data/spec/api/search/cursor_paginated_collection_spec.rb +12 -12
- data/spec/api/search/dynamic_fields_spec.rb +4 -4
- data/spec/api/search/faceting_spec.rb +55 -52
- data/spec/api/search/highlighting_spec.rb +7 -7
- data/spec/api/search/hits_spec.rb +43 -29
- data/spec/api/search/paginated_collection_spec.rb +18 -18
- data/spec/api/search/results_spec.rb +13 -13
- data/spec/api/search/search_spec.rb +3 -3
- data/spec/api/search/stats_spec.rb +10 -10
- data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +19 -18
- data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +9 -9
- data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +10 -6
- data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +10 -10
- data/spec/api/session_proxy/sharding_session_proxy_spec.rb +14 -13
- data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +2 -2
- data/spec/api/session_proxy/spec_helper.rb +1 -1
- data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +9 -5
- data/spec/api/session_spec.rb +42 -42
- data/spec/api/sunspot_spec.rb +7 -4
- data/spec/helpers/integration_helper.rb +1 -0
- data/spec/integration/atomic_updates_spec.rb +25 -11
- data/spec/integration/dynamic_fields_spec.rb +10 -10
- data/spec/integration/faceting_spec.rb +252 -39
- data/spec/integration/field_grouping_spec.rb +35 -16
- data/spec/integration/field_lists_spec.rb +57 -0
- data/spec/integration/geospatial_spec.rb +34 -8
- data/spec/integration/highlighting_spec.rb +5 -5
- data/spec/integration/indexing_spec.rb +5 -5
- data/spec/integration/join_spec.rb +45 -0
- data/spec/integration/keyword_search_spec.rb +47 -45
- data/spec/integration/local_search_spec.rb +4 -4
- data/spec/integration/more_like_this_spec.rb +7 -7
- data/spec/integration/scoped_search_spec.rb +108 -108
- data/spec/integration/spellcheck_spec.rb +52 -7
- data/spec/integration/stats_spec.rb +54 -13
- data/spec/integration/stored_fields_spec.rb +1 -1
- data/spec/integration/test_pagination.rb +4 -4
- data/spec/integration/unicode_spec.rb +1 -1
- data/spec/mocks/adapters.rb +33 -0
- data/spec/mocks/photo.rb +14 -4
- data/spec/mocks/post.rb +9 -1
- data/spec/spec_helper.rb +11 -10
- data/sunspot.gemspec +3 -1
- metadata +49 -6
@@ -6,7 +6,7 @@ describe 'faceting', :type => :search do
|
|
6
6
|
result = session.search Post do
|
7
7
|
facet :title
|
8
8
|
end
|
9
|
-
result.facet(:title).field_name.
|
9
|
+
expect(result.facet(:title).field_name).to eq(:title)
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'returns facet specified by string' do
|
@@ -14,7 +14,7 @@ describe 'faceting', :type => :search do
|
|
14
14
|
result = session.search Post do
|
15
15
|
facet :title
|
16
16
|
end
|
17
|
-
result.facet('title').field_name.
|
17
|
+
expect(result.facet('title').field_name).to eq(:title)
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'returns all facets specified by search' do
|
@@ -24,8 +24,8 @@ describe 'faceting', :type => :search do
|
|
24
24
|
facet :title
|
25
25
|
facet :blog_id
|
26
26
|
end
|
27
|
-
result.facets.first.field_name.
|
28
|
-
result.facets.last.field_name.
|
27
|
+
expect(result.facets.first.field_name).to eq(:title)
|
28
|
+
expect(result.facets.last.field_name).to eq(:blog_id)
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'returns string facet' do
|
@@ -33,7 +33,7 @@ describe 'faceting', :type => :search do
|
|
33
33
|
result = session.search Post do
|
34
34
|
facet :title
|
35
35
|
end
|
36
|
-
facet_values(result, :title).
|
36
|
+
expect(facet_values(result, :title)).to eq(['Author 1', 'Author 2'])
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'returns counts for facet' do
|
@@ -41,7 +41,7 @@ describe 'faceting', :type => :search do
|
|
41
41
|
result = session.search Post do
|
42
42
|
facet :title
|
43
43
|
end
|
44
|
-
facet_counts(result, :title).
|
44
|
+
expect(facet_counts(result, :title)).to eq([2, 1])
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'returns integer facet' do
|
@@ -49,7 +49,7 @@ describe 'faceting', :type => :search do
|
|
49
49
|
result = session.search Post do
|
50
50
|
facet :blog_id
|
51
51
|
end
|
52
|
-
facet_values(result, :blog_id).
|
52
|
+
expect(facet_values(result, :blog_id)).to eq([3, 1])
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'returns float facet' do
|
@@ -57,7 +57,7 @@ describe 'faceting', :type => :search do
|
|
57
57
|
result = session.search Post do
|
58
58
|
facet :average_rating
|
59
59
|
end
|
60
|
-
facet_values(result, :average_rating).
|
60
|
+
expect(facet_values(result, :average_rating)).to eq([9.3, 1.1])
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'returns time facet' do
|
@@ -77,10 +77,11 @@ describe 'faceting', :type => :search do
|
|
77
77
|
rescue ArgumentError
|
78
78
|
DateTime.civil(2050, 4, 7, 20, 27, 15)
|
79
79
|
end
|
80
|
-
facet_values(result, :published_at).
|
80
|
+
expect(facet_values(result, :published_at)).to eq(
|
81
81
|
[Time.gm(2009, 4, 7, 20, 25, 23),
|
82
82
|
Time.gm(2009, 4, 7, 20, 26, 19),
|
83
83
|
future_time]
|
84
|
+
)
|
84
85
|
end
|
85
86
|
|
86
87
|
it 'returns date facet' do
|
@@ -92,9 +93,10 @@ describe 'faceting', :type => :search do
|
|
92
93
|
result = session.search(Post) do
|
93
94
|
facet :expire_date
|
94
95
|
end
|
95
|
-
facet_values(result, :expire_date).
|
96
|
+
expect(facet_values(result, :expire_date)).to eq(
|
96
97
|
[Date.new(2009, 07, 13),
|
97
98
|
Date.new(2009, 04, 01)]
|
99
|
+
)
|
98
100
|
end
|
99
101
|
|
100
102
|
it 'returns trie integer facet' do
|
@@ -102,7 +104,7 @@ describe 'faceting', :type => :search do
|
|
102
104
|
result = session.search Photo do
|
103
105
|
facet :size
|
104
106
|
end
|
105
|
-
facet_values(result, :size).
|
107
|
+
expect(facet_values(result, :size)).to eq([3, 1])
|
106
108
|
end
|
107
109
|
|
108
110
|
it 'returns float facet' do
|
@@ -110,7 +112,7 @@ describe 'faceting', :type => :search do
|
|
110
112
|
result = session.search Photo do
|
111
113
|
facet :average_rating
|
112
114
|
end
|
113
|
-
facet_values(result, :average_rating).
|
115
|
+
expect(facet_values(result, :average_rating)).to eq([9.3, 1.1])
|
114
116
|
end
|
115
117
|
|
116
118
|
it 'returns time facet' do
|
@@ -122,15 +124,16 @@ describe 'faceting', :type => :search do
|
|
122
124
|
result = session.search Photo do
|
123
125
|
facet :created_at
|
124
126
|
end
|
125
|
-
facet_values(result, :created_at).
|
127
|
+
expect(facet_values(result, :created_at)).to eq(
|
126
128
|
[Time.gm(2009, 04, 07, 20, 25, 23),
|
127
129
|
Time.gm(2009, 04, 07, 20, 26, 19)]
|
130
|
+
)
|
128
131
|
end
|
129
132
|
|
130
133
|
it 'returns boolean facet' do
|
131
134
|
stub_facet(:featured_bs, 'true' => 3, 'false' => 1)
|
132
135
|
result = session.search(Post) { facet(:featured) }
|
133
|
-
facet_values(result, :featured).
|
136
|
+
expect(facet_values(result, :featured)).to eq([true, false])
|
134
137
|
end
|
135
138
|
|
136
139
|
|
@@ -138,26 +141,26 @@ describe 'faceting', :type => :search do
|
|
138
141
|
it "returns field facet with #{type} custom name" do
|
139
142
|
stub_facet(:blog, '2' => 1, '1' => 4)
|
140
143
|
result = session.search(Post) { facet(:blog_id, :name => name) }
|
141
|
-
facet_values(result, :blog).
|
144
|
+
expect(facet_values(result, :blog)).to eq([1, 2])
|
142
145
|
end
|
143
146
|
|
144
147
|
it "assigns #{type} custom name to field facet" do
|
145
148
|
stub_facet(:blog, '2' => 1)
|
146
149
|
result = session.search(Post) { facet(:blog_id, :name => name) }
|
147
|
-
result.facet(:blog).name.
|
150
|
+
expect(result.facet(:blog).name).to eq(:blog)
|
148
151
|
end
|
149
152
|
|
150
153
|
it "retains field name for #{type} custom-named field facet" do
|
151
154
|
stub_facet(:blog, '2' => 1)
|
152
155
|
result = session.search(Post) { facet(:blog_id, :name => name) }
|
153
|
-
result.facet(:blog).field_name.
|
156
|
+
expect(result.facet(:blog).field_name).to eq(:blog_id)
|
154
157
|
end
|
155
158
|
end
|
156
159
|
|
157
160
|
it 'returns class facet' do
|
158
161
|
stub_facet(:class_name, 'Post' => 3, 'Namespaced::Comment' => 1)
|
159
162
|
result = session.search(Post) { facet(:class) }
|
160
|
-
facet_values(result, :class).
|
163
|
+
expect(facet_values(result, :class)).to eq([Post, Namespaced::Comment])
|
161
164
|
end
|
162
165
|
|
163
166
|
it 'returns special :any facet' do
|
@@ -166,8 +169,8 @@ describe 'faceting', :type => :search do
|
|
166
169
|
)
|
167
170
|
search = session.search(Post) { facet(:category_ids, :extra => :any) }
|
168
171
|
row = search.facet(:category_ids).rows.first
|
169
|
-
row.value.
|
170
|
-
row.count.
|
172
|
+
expect(row.value).to eq(:any)
|
173
|
+
expect(row.count).to eq(3)
|
171
174
|
end
|
172
175
|
|
173
176
|
it 'returns special :none facet' do
|
@@ -176,8 +179,8 @@ describe 'faceting', :type => :search do
|
|
176
179
|
)
|
177
180
|
search = session.search(Post) { facet(:category_ids, :extra => :none) }
|
178
181
|
row = search.facet(:category_ids).rows.first
|
179
|
-
row.value.
|
180
|
-
row.count.
|
182
|
+
expect(row.value).to eq(:none)
|
183
|
+
expect(row.count).to eq(3)
|
181
184
|
end
|
182
185
|
|
183
186
|
it 'returns date range facet' do
|
@@ -186,8 +189,8 @@ describe 'faceting', :type => :search do
|
|
186
189
|
end_time = start_time + 2*24*60*60
|
187
190
|
result = session.search(Post) { facet(:published_at, :time_range => start_time..end_time) }
|
188
191
|
facet = result.facet(:published_at)
|
189
|
-
facet.rows.first.value.
|
190
|
-
facet.rows.last.value.
|
192
|
+
expect(facet.rows.first.value).to eq(start_time..(start_time+24*60*60))
|
193
|
+
expect(facet.rows.last.value).to eq((start_time+24*60*60)..end_time)
|
191
194
|
end
|
192
195
|
|
193
196
|
it 'returns date range facet sorted by count' do
|
@@ -196,8 +199,8 @@ describe 'faceting', :type => :search do
|
|
196
199
|
end_time = start_time + 2*24*60*60
|
197
200
|
result = session.search(Post) { facet(:published_at, :time_range => start_time..end_time, :sort => :count) }
|
198
201
|
facet = result.facet(:published_at)
|
199
|
-
facet.rows.first.value.
|
200
|
-
facet.rows.last.value.
|
202
|
+
expect(facet.rows.first.value).to eq((start_time+24*60*60)..end_time)
|
203
|
+
expect(facet.rows.last.value).to eq(start_time..(start_time+24*60*60))
|
201
204
|
end
|
202
205
|
|
203
206
|
it 'returns query facet' do
|
@@ -216,10 +219,10 @@ describe 'faceting', :type => :search do
|
|
216
219
|
end
|
217
220
|
end
|
218
221
|
facet = search.facet(:average_rating)
|
219
|
-
facet.rows.first.value.
|
220
|
-
facet.rows.first.count.
|
221
|
-
facet.rows.last.value.
|
222
|
-
facet.rows.last.count.
|
222
|
+
expect(facet.rows.first.value).to eq(3.0..5.0)
|
223
|
+
expect(facet.rows.first.count).to eq(3)
|
224
|
+
expect(facet.rows.last.value).to eq(1.0..3.0)
|
225
|
+
expect(facet.rows.last.count).to eq(1)
|
223
226
|
end
|
224
227
|
|
225
228
|
describe 'query facet option handling' do
|
@@ -244,43 +247,43 @@ describe 'faceting', :type => :search do
|
|
244
247
|
end
|
245
248
|
|
246
249
|
it 'sorts in order of specification if no limit is given' do
|
247
|
-
facet_values_from_options.
|
250
|
+
expect(facet_values_from_options).to eq([1, 3, 2])
|
248
251
|
end
|
249
252
|
|
250
253
|
it 'sorts lexically if lexical option is specified' do
|
251
|
-
facet_values_from_options(:sort => :index).
|
254
|
+
expect(facet_values_from_options(:sort => :index)).to eq([1, 2, 3])
|
252
255
|
end
|
253
256
|
|
254
257
|
it 'sorts by count by default if limit is given' do
|
255
|
-
facet_values_from_options(:limit => 2).
|
258
|
+
expect(facet_values_from_options(:limit => 2)).to eq([2, 1])
|
256
259
|
end
|
257
260
|
|
258
261
|
it 'sorts by count if count option is specified' do
|
259
|
-
facet_values_from_options(:sort => :count).
|
262
|
+
expect(facet_values_from_options(:sort => :count)).to eq([2, 1, 3])
|
260
263
|
end
|
261
264
|
|
262
265
|
it 'sorts lexically if lexical option is specified even if limit is given' do
|
263
|
-
facet_values_from_options(:sort => :index, :limit => 2).
|
266
|
+
expect(facet_values_from_options(:sort => :index, :limit => 2)).to eq([1, 2])
|
264
267
|
end
|
265
268
|
|
266
269
|
it 'limits facets if limit option is given' do
|
267
|
-
facet_values_from_options(:limit => 1).
|
270
|
+
expect(facet_values_from_options(:limit => 1)).to eq([2])
|
268
271
|
end
|
269
272
|
|
270
273
|
it 'does not limit facets if limit option is negative' do
|
271
|
-
facet_values_from_options(:limit => -2).
|
274
|
+
expect(facet_values_from_options(:limit => -2)).to eq([1, 3, 2])
|
272
275
|
end
|
273
276
|
|
274
277
|
it 'returns all facets if limit greater than number of facets' do
|
275
|
-
facet_values_from_options(:limit => 10).
|
278
|
+
expect(facet_values_from_options(:limit => 10)).to eq([2, 1, 3])
|
276
279
|
end
|
277
280
|
|
278
281
|
it 'allows zero count if specified' do
|
279
|
-
facet_values_from_options(:zeros => true).
|
282
|
+
expect(facet_values_from_options(:zeros => true)).to eq([1, 3, 2, 4])
|
280
283
|
end
|
281
284
|
|
282
285
|
it 'sets minimum count' do
|
283
|
-
facet_values_from_options(:minimum_count => 2).
|
286
|
+
expect(facet_values_from_options(:minimum_count => 2)).to eq([1, 2])
|
284
287
|
end
|
285
288
|
end
|
286
289
|
|
@@ -293,17 +296,17 @@ describe 'faceting', :type => :search do
|
|
293
296
|
facet :category_ids, :only => [1, 3, 5]
|
294
297
|
end
|
295
298
|
facet = search.facet(:category_ids)
|
296
|
-
facet.rows.first.value.
|
297
|
-
facet.rows.first.count.
|
298
|
-
facet.rows.last.value.
|
299
|
-
facet.rows.last.count.
|
299
|
+
expect(facet.rows.first.value).to eq(1)
|
300
|
+
expect(facet.rows.first.count).to eq(3)
|
301
|
+
expect(facet.rows.last.value).to eq(3)
|
302
|
+
expect(facet.rows.last.count).to eq(1)
|
300
303
|
end
|
301
304
|
|
302
305
|
it 'returns instantiated facet values' do
|
303
306
|
blogs = Array.new(2) { Blog.new }
|
304
307
|
stub_facet(:blog_id_i, blogs[0].id.to_s => 2, blogs[1].id.to_s => 1)
|
305
308
|
search = session.search(Post) { facet(:blog_id) }
|
306
|
-
search.facet(:blog_id).rows.map { |row| row.instance }.
|
309
|
+
expect(search.facet(:blog_id).rows.map { |row| row.instance }).to eq(blogs)
|
307
310
|
end
|
308
311
|
|
309
312
|
it 'returns all instantiated facet rows, whether or not the instances exist' do
|
@@ -311,7 +314,7 @@ describe 'faceting', :type => :search do
|
|
311
314
|
blogs.last.destroy
|
312
315
|
stub_facet(:blog_id_i, blogs[0].id.to_s => 2, blogs[1].id.to_s => 1)
|
313
316
|
search = session.search(Post) { facet(:blog_id) }
|
314
|
-
search.facet(:blog_id).rows.map { |row| row.instance }.
|
317
|
+
expect(search.facet(:blog_id).rows.map { |row| row.instance }).to eq([blogs.first, nil])
|
315
318
|
end
|
316
319
|
|
317
320
|
it 'returns only rows with available instances if specified' do
|
@@ -319,7 +322,7 @@ describe 'faceting', :type => :search do
|
|
319
322
|
blogs.last.destroy
|
320
323
|
stub_facet(:blog_id_i, blogs[0].id.to_s => 2, blogs[1].id.to_s => 1)
|
321
324
|
search = session.search(Post) { facet(:blog_id) }
|
322
|
-
search.facet(:blog_id).rows(:verify => true).map { |row| row.instance }.
|
325
|
+
expect(search.facet(:blog_id).rows(:verify => true).map { |row| row.instance }).to eq(blogs[0..0])
|
323
326
|
end
|
324
327
|
|
325
328
|
it 'returns both verified and unverified rows from the same facet' do
|
@@ -327,14 +330,14 @@ describe 'faceting', :type => :search do
|
|
327
330
|
blogs.last.destroy
|
328
331
|
stub_facet(:blog_id_i, blogs[0].id.to_s => 2, blogs[1].id.to_s => 1)
|
329
332
|
search = session.search(Post) { facet(:blog_id) }
|
330
|
-
search.facet(:blog_id).rows(:verify => true).map { |row| row.instance }.
|
331
|
-
search.facet(:blog_id).rows.map { |row| row.instance }.
|
333
|
+
expect(search.facet(:blog_id).rows(:verify => true).map { |row| row.instance }).to eq(blogs[0..0])
|
334
|
+
expect(search.facet(:blog_id).rows.map { |row| row.instance }).to eq([blogs.first, nil])
|
332
335
|
end
|
333
336
|
|
334
337
|
it 'ignores :verify option if facet not a reference facet' do
|
335
338
|
stub_facet(:category_ids_im, '1' => 2, '2' => 1)
|
336
339
|
search = session.search(Post) { facet(:category_ids) }
|
337
|
-
search.facet(:category_ids).
|
340
|
+
expect(search.facet(:category_ids).rows(:verify => true).size).to eq(2)
|
338
341
|
end
|
339
342
|
|
340
343
|
it 'returns instantiated facet values for limited field facet' do
|
@@ -346,7 +349,7 @@ describe 'faceting', :type => :search do
|
|
346
349
|
search = session.search(Post) do
|
347
350
|
facet(:blog_id, :only => blogs.map { |blog| blog.id })
|
348
351
|
end
|
349
|
-
search.facet(:blog_id).rows.map { |row| row.instance }.
|
352
|
+
expect(search.facet(:blog_id).rows.map { |row| row.instance }).to eq(blogs)
|
350
353
|
end
|
351
354
|
|
352
355
|
it 'only queries the persistent store once for an instantiated facet' do
|
@@ -355,6 +358,6 @@ describe 'faceting', :type => :search do
|
|
355
358
|
stub_facet(:blog_id_i, blogs[0].id.to_s => 2, blogs[1].id.to_s => 1)
|
356
359
|
result = session.search(Post) { facet(:blog_id) }
|
357
360
|
result.facet(:blog_id).rows.each { |row| row.instance }
|
358
|
-
(Blog.query_count - query_count).
|
361
|
+
expect(Blog.query_count - query_count).to eq(1)
|
359
362
|
end
|
360
363
|
end
|
@@ -14,38 +14,38 @@ describe 'search with highlighting results', :type => :search do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'returns all highlights' do
|
17
|
-
@search.hits.last.
|
17
|
+
expect(@search.hits.last.highlights.size).to eq(3)
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'returns all highlights for a specified field' do
|
21
|
-
@search.hits.last.
|
21
|
+
expect(@search.hits.last.highlights(:body).size).to eq(2)
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'returns first highlight for a specified field' do
|
25
|
-
@search.hits.first.highlight(:title).format.
|
25
|
+
expect(@search.hits.first.highlight(:title).format).to eq('one <em>two</em> three')
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'returns an empty array if a given field does not have a highlight' do
|
29
|
-
@search.hits.first.highlights(:body).
|
29
|
+
expect(@search.hits.first.highlights(:body)).to eq([])
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'formats hits with <em> by default' do
|
33
33
|
highlight = @search.hits.first.highlights(:title).first.formatted
|
34
|
-
highlight.
|
34
|
+
expect(highlight).to eq('one <em>two</em> three')
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'formats hits with provided block' do
|
38
38
|
highlight = @search.hits.first.highlights(:title).first.format do |word|
|
39
39
|
"<i>#{word}</i>"
|
40
40
|
end
|
41
|
-
highlight.
|
41
|
+
expect(highlight).to eq('one <i>two</i> three')
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'handles multiple highlighted words' do
|
45
45
|
highlight = @search.hits.last.highlights(:body).last.format do |word|
|
46
46
|
"<b>#{word}</b>"
|
47
47
|
end
|
48
|
-
highlight.
|
48
|
+
expect(highlight).to eq('<b>eight</b> nine <b>ten</b>')
|
49
49
|
end
|
50
50
|
|
51
51
|
private
|
@@ -5,37 +5,51 @@ describe 'hits', :type => :search do
|
|
5
5
|
post_1, post_2 = Array.new(2) { Post.new }
|
6
6
|
stub_results(post_1, post_2)
|
7
7
|
%w(load load_all).each do |message|
|
8
|
-
MockAdapter::DataAccessor.
|
8
|
+
expect(MockAdapter::DataAccessor).not_to receive(message)
|
9
9
|
end
|
10
|
-
session.search(Post).hits.map do |hit|
|
10
|
+
expect(session.search(Post).hits.map do |hit|
|
11
11
|
[hit.class_name, hit.primary_key]
|
12
|
-
end.
|
12
|
+
end).to eq([['Post', post_1.id.to_s], ['Post', post_2.id.to_s]])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return ID prefix when used with compositeId shard router" do
|
16
|
+
Sunspot.index!(ModelWithPrefixId.new)
|
17
|
+
|
18
|
+
expect(Sunspot.search(ModelWithPrefixId).
|
19
|
+
hits.map { |h| h.id_prefix }.uniq).to eq ["USERDATA!"]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should parse nested ID prefixes" do
|
23
|
+
Sunspot.index!(ModelWithNestedPrefixId.new)
|
24
|
+
|
25
|
+
expect(Sunspot.search(ModelWithNestedPrefixId).
|
26
|
+
hits.map { |h| h.id_prefix }.uniq).to eq ["USER!USERDATA!"]
|
13
27
|
end
|
14
28
|
|
15
29
|
it 'returns search total as attribute of hits' do
|
16
30
|
stub_results(Post.new, 4)
|
17
|
-
session.search(Post) do
|
31
|
+
expect(session.search(Post) do
|
18
32
|
paginate(:page => 1)
|
19
|
-
end.hits.total_entries.
|
33
|
+
end.hits.total_entries).to eq(4)
|
20
34
|
end
|
21
35
|
|
22
36
|
it 'returns search total as attribute of verified hits' do
|
23
37
|
stub_results(Post.new, 4)
|
24
|
-
session.search(Post) do
|
38
|
+
expect(session.search(Post) do
|
25
39
|
paginate(:page => 1)
|
26
|
-
end.hits(:verify => true).total_entries.
|
40
|
+
end.hits(:verify => true).total_entries).to eq(4)
|
27
41
|
end
|
28
42
|
|
29
43
|
it 'should return instance from hit' do
|
30
44
|
posts = Array.new(2) { Post.new }
|
31
45
|
stub_results(*posts)
|
32
|
-
session.search(Post).hits.first.instance.
|
46
|
+
expect(session.search(Post).hits.first.instance).to eq(posts.first)
|
33
47
|
end
|
34
48
|
|
35
49
|
it 'should return the instance primary key when you use it as a param' do
|
36
50
|
posts = Array.new(2) { Post.new }
|
37
51
|
stub_results(*posts)
|
38
|
-
session.search(Post).hits.first.to_param.
|
52
|
+
expect(session.search(Post).hits.first.to_param).to eq(posts.first.id.to_s)
|
39
53
|
end
|
40
54
|
|
41
55
|
it 'should provide iterator over hits with instances' do
|
@@ -49,8 +63,8 @@ describe 'hits', :type => :search do
|
|
49
63
|
results << result
|
50
64
|
end
|
51
65
|
|
52
|
-
hits.
|
53
|
-
results.
|
66
|
+
expect(hits.size).to eq(2)
|
67
|
+
expect(results.size).to eq(2)
|
54
68
|
end
|
55
69
|
|
56
70
|
it 'should provide an Enumerator over hits with instances' do
|
@@ -59,9 +73,9 @@ describe 'hits', :type => :search do
|
|
59
73
|
search = session.search(Post)
|
60
74
|
hits, results = [], []
|
61
75
|
search.each_hit_with_result.with_index do |(hit, result), index|
|
62
|
-
hit.
|
63
|
-
result.
|
64
|
-
index.
|
76
|
+
expect(hit).to be_kind_of(Sunspot::Search::Hit)
|
77
|
+
expect(result).to be_kind_of(Post)
|
78
|
+
expect(index).to be_kind_of(Integer)
|
65
79
|
end
|
66
80
|
end
|
67
81
|
|
@@ -71,9 +85,9 @@ describe 'hits', :type => :search do
|
|
71
85
|
search = session.search(Post)
|
72
86
|
search.hits.first.instance
|
73
87
|
%w(load load_all).each do |message|
|
74
|
-
MockAdapter::DataAccessor.
|
88
|
+
expect(MockAdapter::DataAccessor).not_to receive(message)
|
75
89
|
end
|
76
|
-
search.hits.last.instance.
|
90
|
+
expect(search.hits.last.instance).to eq(posts.last)
|
77
91
|
end
|
78
92
|
|
79
93
|
it 'should return only hits whose referenced object exists in the data store if :verify option passed' do
|
@@ -81,7 +95,7 @@ describe 'hits', :type => :search do
|
|
81
95
|
posts.last.destroy
|
82
96
|
stub_results(*posts)
|
83
97
|
search = session.search(Post)
|
84
|
-
search.hits(:verify => true).map { |hit| hit.instance }.
|
98
|
+
expect(search.hits(:verify => true).map { |hit| hit.instance }).to eq(posts[0..0])
|
85
99
|
end
|
86
100
|
|
87
101
|
it 'should return verified and unverified hits from the same search' do
|
@@ -89,59 +103,59 @@ describe 'hits', :type => :search do
|
|
89
103
|
posts.last.destroy
|
90
104
|
stub_results(*posts)
|
91
105
|
search = session.search(Post)
|
92
|
-
search.hits(:verify => true).map { |hit| hit.instance }.
|
93
|
-
search.hits.map { |hit| hit.instance }.
|
106
|
+
expect(search.hits(:verify => true).map { |hit| hit.instance }).to eq(posts[0..0])
|
107
|
+
expect(search.hits.map { |hit| hit.instance }).to eq([posts.first, nil])
|
94
108
|
end
|
95
109
|
|
96
110
|
it 'should attach score to hits' do
|
97
111
|
stub_full_results('instance' => Post.new, 'score' => 1.23)
|
98
|
-
session.search(Post).hits.first.score.
|
112
|
+
expect(session.search(Post).hits.first.score).to eq(1.23)
|
99
113
|
end
|
100
114
|
|
101
115
|
it 'should return stored field values in hits' do
|
102
116
|
stub_full_results('instance' => Post.new, 'title_ss' => 'Title')
|
103
|
-
session.search(Post).hits.first.stored(:title).
|
117
|
+
expect(session.search(Post).hits.first.stored(:title)).to eq('Title')
|
104
118
|
end
|
105
119
|
|
106
120
|
it 'should return stored field values for searches against multiple types' do
|
107
121
|
stub_full_results('instance' => Post.new, 'title_ss' => 'Title')
|
108
|
-
session.search(Post, Namespaced::Comment).hits.first.stored(:title).
|
122
|
+
expect(session.search(Post, Namespaced::Comment).hits.first.stored(:title)).to eq('Title')
|
109
123
|
end
|
110
124
|
|
111
125
|
it 'should return stored field values for searches against base type when subtype matches' do
|
112
126
|
class SubclassedPost < Post; end;
|
113
127
|
stub_full_results('instance' => SubclassedPost.new, 'title_ss' => 'Title')
|
114
|
-
session.search(Post).hits.first.stored(:title).
|
128
|
+
expect(session.search(Post).hits.first.stored(:title)).to eq('Title')
|
115
129
|
end
|
116
130
|
|
117
131
|
it 'should return stored text fields' do
|
118
132
|
stub_full_results('instance' => Post.new, 'body_textsv' => 'Body')
|
119
|
-
session.search(Post, Namespaced::Comment).hits.first.stored(:body).
|
133
|
+
expect(session.search(Post, Namespaced::Comment).hits.first.stored(:body)).to eq('Body')
|
120
134
|
end
|
121
135
|
|
122
136
|
it 'should return stored boolean fields' do
|
123
137
|
stub_full_results('instance' => Post.new, 'featured_bs' => true)
|
124
|
-
session.search(Post, Namespaced::Comment).hits.first.stored(:featured).
|
138
|
+
expect(session.search(Post, Namespaced::Comment).hits.first.stored(:featured)).to be(true)
|
125
139
|
end
|
126
140
|
|
127
141
|
it 'should return stored boolean fields that evaluate to false' do
|
128
142
|
stub_full_results('instance' => Post.new, 'featured_bs' => false)
|
129
|
-
session.search(Post, Namespaced::Comment).hits.first.stored(:featured).
|
143
|
+
expect(session.search(Post, Namespaced::Comment).hits.first.stored(:featured)).to eq(false)
|
130
144
|
end
|
131
145
|
|
132
146
|
it 'should return stored dynamic fields' do
|
133
147
|
stub_full_results('instance' => Post.new, 'custom_string:test_ss' => 'Custom')
|
134
|
-
session.search(Post, Namespaced::Comment).hits.first.stored(:custom_string, :test).
|
148
|
+
expect(session.search(Post, Namespaced::Comment).hits.first.stored(:custom_string, :test)).to eq('Custom')
|
135
149
|
end
|
136
150
|
|
137
151
|
it 'should typecast stored field values in hits' do
|
138
152
|
time = Time.utc(2008, 7, 8, 2, 45)
|
139
153
|
stub_full_results('instance' => Post.new, 'last_indexed_at_ds' => time.xmlschema)
|
140
|
-
session.search(Post).hits.first.stored(:last_indexed_at).
|
154
|
+
expect(session.search(Post).hits.first.stored(:last_indexed_at)).to eq(time)
|
141
155
|
end
|
142
156
|
|
143
157
|
it 'should return stored values for multi-valued fields' do
|
144
158
|
stub_full_results('instance' => User.new, 'role_ids_ims' => %w(1 4 5))
|
145
|
-
session.search(User).hits.first.stored(:role_ids).
|
159
|
+
expect(session.search(User).hits.first.stored(:role_ids)).to eq([1, 4, 5])
|
146
160
|
end
|
147
161
|
end
|
@@ -3,7 +3,7 @@ require File.expand_path('spec_helper', File.dirname(__FILE__))
|
|
3
3
|
describe "PaginatedCollection" do
|
4
4
|
subject { Sunspot::Search::PaginatedCollection.new [], 1, 10, 20 }
|
5
5
|
|
6
|
-
it { subject.
|
6
|
+
it { expect(subject).to be_an(Array) }
|
7
7
|
|
8
8
|
describe "#send" do
|
9
9
|
it 'should allow send' do
|
@@ -13,37 +13,37 @@ describe "PaginatedCollection" do
|
|
13
13
|
|
14
14
|
describe "#respond_to?" do
|
15
15
|
it 'should return true for current_page' do
|
16
|
-
subject.respond_to?(:current_page).
|
16
|
+
expect(subject.respond_to?(:current_page)).to be(true)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
context "behaves like a WillPaginate::Collection" do
|
21
|
-
it { subject.total_entries.
|
22
|
-
it { subject.total_pages.
|
23
|
-
it { subject.current_page.
|
24
|
-
it { subject.per_page.
|
25
|
-
it { subject.previous_page.
|
26
|
-
it { subject.prev_page.
|
27
|
-
it { subject.next_page.
|
28
|
-
it { subject.out_of_bounds
|
29
|
-
it { subject.offset.
|
21
|
+
it { expect(subject.total_entries).to eql(20) }
|
22
|
+
it { expect(subject.total_pages).to eql(2) }
|
23
|
+
it { expect(subject.current_page).to eql(1) }
|
24
|
+
it { expect(subject.per_page).to eql(10) }
|
25
|
+
it { expect(subject.previous_page).to be_nil }
|
26
|
+
it { expect(subject.prev_page).to be_nil }
|
27
|
+
it { expect(subject.next_page).to eql(2) }
|
28
|
+
it { expect(subject.out_of_bounds?).not_to be(true) }
|
29
|
+
it { expect(subject.offset).to eql(0) }
|
30
30
|
|
31
31
|
it 'should allow setting total_count' do
|
32
32
|
subject.total_count = 1
|
33
|
-
subject.total_count.
|
33
|
+
expect(subject.total_count).to eql(1)
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'should allow setting total_entries' do
|
37
37
|
subject.total_entries = 1
|
38
|
-
subject.total_entries.
|
38
|
+
expect(subject.total_entries).to eql(1)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
context "behaves like Kaminari" do
|
43
|
-
it { subject.total_count.
|
44
|
-
it { subject.num_pages.
|
45
|
-
it { subject.limit_value.
|
46
|
-
it { subject.first_page
|
47
|
-
it { subject.last_page
|
43
|
+
it { expect(subject.total_count).to eql(20) }
|
44
|
+
it { expect(subject.num_pages).to eql(2) }
|
45
|
+
it { expect(subject.limit_value).to eql(10) }
|
46
|
+
it { expect(subject.first_page?).to be(true) }
|
47
|
+
it { expect(subject.last_page?).not_to be(true) }
|
48
48
|
end
|
49
49
|
end
|