sunspot 0.10.5 → 0.10.6
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -0
- data/README.rdoc +3 -3
- data/TODO +4 -5
- data/VERSION.yml +1 -1
- data/bin/sunspot-solr +18 -6
- data/lib/sunspot/dsl/field_query.rb +69 -18
- data/lib/sunspot/dsl/fields.rb +6 -5
- data/lib/sunspot/dsl/fulltext.rb +57 -1
- data/lib/sunspot/dsl/query.rb +30 -3
- data/lib/sunspot/dsl/query_facet.rb +8 -3
- data/lib/sunspot/dsl/search.rb +1 -1
- data/lib/sunspot/dsl.rb +1 -1
- data/lib/sunspot/field_factory.rb +6 -3
- data/lib/sunspot/query/abstract_field_facet.rb +43 -0
- data/lib/sunspot/query/date_field_facet.rb +14 -0
- data/lib/sunspot/query/dismax.rb +26 -7
- data/lib/sunspot/query/field_facet.rb +2 -122
- data/lib/sunspot/query/highlighting.rb +17 -5
- data/lib/sunspot/query/query.rb +12 -23
- data/lib/sunspot/query/query_facet.rb +4 -66
- data/lib/sunspot/query.rb +5 -1
- data/lib/sunspot/search/date_facet.rb +35 -0
- data/lib/sunspot/search/facet_row.rb +27 -0
- data/lib/sunspot/search/field_facet.rb +44 -0
- data/lib/sunspot/search/hit.rb +10 -6
- data/lib/sunspot/search/query_facet.rb +62 -0
- data/lib/sunspot/search.rb +22 -44
- data/lib/sunspot/setup.rb +22 -7
- data/lib/sunspot/type.rb +4 -0
- data/lib/sunspot/util.rb +8 -0
- data/lib/sunspot.rb +7 -6
- data/solr/solr/conf/solrconfig.xml +1 -2
- data/solr/solr/lib/locallucene.jar +0 -0
- data/solr/solr/lib/localsolr.jar +0 -0
- data/spec/api/indexer/attributes_spec.rb +5 -0
- data/spec/api/query/faceting_spec.rb +24 -0
- data/spec/api/query/fulltext_spec.rb +80 -1
- data/spec/api/query/highlighting_spec.rb +84 -6
- data/spec/api/search/faceting_spec.rb +45 -9
- data/spec/api/search/highlighting_spec.rb +2 -2
- data/spec/api/search/hits_spec.rb +5 -0
- data/spec/integration/faceting_spec.rb +19 -0
- data/spec/integration/keyword_search_spec.rb +101 -4
- data/spec/mocks/photo.rb +3 -0
- data/tasks/gemspec.rake +8 -2
- data/tasks/rcov.rake +2 -2
- metadata +9 -11
- data/lib/sunspot/facet.rb +0 -24
- data/lib/sunspot/facet_data.rb +0 -169
- data/lib/sunspot/facet_row.rb +0 -12
- data/lib/sunspot/instantiated_facet.rb +0 -39
- data/lib/sunspot/instantiated_facet_row.rb +0 -27
- data/lib/sunspot/query/fulltext_base_query.rb +0 -47
- data/lib/sunspot/query/query_facet_row.rb +0 -19
- data/lib/sunspot/query/query_field_facet.rb +0 -20
data/lib/sunspot/setup.rb
CHANGED
@@ -10,6 +10,7 @@ module Sunspot
|
|
10
10
|
@field_factories, @text_field_factories, @dynamic_field_factories,
|
11
11
|
@field_factories_cache, @text_field_factories_cache,
|
12
12
|
@dynamic_field_factories_cache = *Array.new(6) { Hash.new }
|
13
|
+
@stored_field_factories_cache = Hash.new { |h, k| h[k] = [] }
|
13
14
|
@dsl = DSL::Fields.new(self)
|
14
15
|
add_field_factory(:class, Type::ClassType)
|
15
16
|
end
|
@@ -19,16 +20,16 @@ module Sunspot
|
|
19
20
|
end
|
20
21
|
|
21
22
|
#
|
22
|
-
# Add
|
23
|
-
#
|
24
|
-
# ==== Parameters
|
25
|
-
#
|
26
|
-
# field_factories<Array>:: Array of Sunspot::Field objects
|
23
|
+
# Add field factory for scope/ordering
|
27
24
|
#
|
28
25
|
def add_field_factory(name, type, options = {}, &block)
|
26
|
+
stored = options[:stored]
|
29
27
|
field_factory = FieldFactory::Static.new(name, type, options, &block)
|
30
28
|
@field_factories[field_factory.signature] = field_factory
|
31
29
|
@field_factories_cache[field_factory.name] = field_factory
|
30
|
+
if stored
|
31
|
+
@stored_field_factories_cache[field_factory.name] << field_factory
|
32
|
+
end
|
32
33
|
end
|
33
34
|
|
34
35
|
#
|
@@ -39,9 +40,13 @@ module Sunspot
|
|
39
40
|
# field_factories<Array>:: Array of Sunspot::Field objects
|
40
41
|
#
|
41
42
|
def add_text_field_factory(name, options = {}, &block)
|
43
|
+
stored = options[:stored]
|
42
44
|
field_factory = FieldFactory::Static.new(name, Type::TextType, options, &block)
|
43
45
|
@text_field_factories[name] = field_factory
|
44
46
|
@text_field_factories_cache[field_factory.name] = field_factory
|
47
|
+
if stored
|
48
|
+
@stored_field_factories_cache[field_factory.name] << field_factory
|
49
|
+
end
|
45
50
|
end
|
46
51
|
|
47
52
|
#
|
@@ -62,8 +67,8 @@ module Sunspot
|
|
62
67
|
# of documents during index, but does not actually generate fields (since
|
63
68
|
# the field names used in search are static).
|
64
69
|
#
|
65
|
-
def set_coordinates_field(name)
|
66
|
-
@coordinates_field_factory = FieldFactory::Coordinates.new(name)
|
70
|
+
def set_coordinates_field(name = nil, &block)
|
71
|
+
@coordinates_field_factory = FieldFactory::Coordinates.new(name, &block)
|
67
72
|
end
|
68
73
|
|
69
74
|
#
|
@@ -123,6 +128,16 @@ module Sunspot
|
|
123
128
|
[text_field]
|
124
129
|
end
|
125
130
|
|
131
|
+
#
|
132
|
+
# Return one or more stored fields (can be either attribute or text fields)
|
133
|
+
# for the given name.
|
134
|
+
#
|
135
|
+
def stored_fields(field_name)
|
136
|
+
@stored_field_factories_cache[field_name.to_sym].map do |field_factory|
|
137
|
+
field_factory.build
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
126
141
|
#
|
127
142
|
# Return the DynamicFieldFactory with the given base name
|
128
143
|
#
|
data/lib/sunspot/type.rb
CHANGED
data/lib/sunspot/util.rb
CHANGED
@@ -87,6 +87,14 @@ module Sunspot
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
def extract_options_from(args)
|
91
|
+
if args.last.is_a?(Hash)
|
92
|
+
args.pop
|
93
|
+
else
|
94
|
+
{}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
90
98
|
#
|
91
99
|
# Perform a deep merge of hashes, returning the result as a new hash.
|
92
100
|
# See #deep_merge_into for rules used to merge the hashes
|
data/lib/sunspot.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'time'
|
3
|
+
require 'date'
|
4
|
+
require 'enumerator'
|
1
5
|
begin
|
2
|
-
require 'time'
|
3
|
-
require 'date'
|
4
6
|
require 'rsolr'
|
5
7
|
rescue LoadError
|
6
8
|
require 'rubygems'
|
@@ -10,8 +12,7 @@ end
|
|
10
12
|
require File.join(File.dirname(__FILE__), 'light_config')
|
11
13
|
|
12
14
|
%w(util adapters configuration setup composite_setup text_field_setup field
|
13
|
-
field_factory data_extractor indexer query search
|
14
|
-
instantiated_facet instantiated_facet_row facet_data session type
|
15
|
+
field_factory data_extractor indexer query search session type
|
15
16
|
dsl).each do |filename|
|
16
17
|
require File.join(File.dirname(__FILE__), 'sunspot', filename)
|
17
18
|
end
|
@@ -210,7 +211,7 @@ module Sunspot
|
|
210
211
|
# ==== Parameters
|
211
212
|
#
|
212
213
|
# types<Class>...::
|
213
|
-
#
|
214
|
+
# One or more types to search for. If no types are passed, all
|
214
215
|
# configured types will be searched for.
|
215
216
|
#
|
216
217
|
# ==== Returns
|
@@ -229,7 +230,7 @@ module Sunspot
|
|
229
230
|
# ==== Parameters
|
230
231
|
#
|
231
232
|
# types<Class>...::
|
232
|
-
#
|
233
|
+
# One or more types to search for. If no types are passed, all
|
233
234
|
# configured types will be searched.
|
234
235
|
#
|
235
236
|
# ==== Returns
|
@@ -682,9 +682,7 @@
|
|
682
682
|
</queryResponseWriter>
|
683
683
|
|
684
684
|
|
685
|
-
<!-- example of registering a query parser
|
686
685
|
<queryParser name="lucene" class="org.apache.solr.search.LuceneQParserPlugin"/>
|
687
|
-
-->
|
688
686
|
|
689
687
|
<!-- example of registering a custom function parser
|
690
688
|
<valueSourceParser name="myfunc" class="com.mycompany.MyValueSourceParser" />
|
@@ -715,6 +713,7 @@
|
|
715
713
|
<str name='lngField'>long</str>
|
716
714
|
</searchComponent>
|
717
715
|
<requestHandler class='org.apache.solr.handler.component.SearchHandler' name='geo'>
|
716
|
+
<str name="defType">lucene</str>
|
718
717
|
<arr name='components'>
|
719
718
|
<str>localsolr</str>
|
720
719
|
<str>facet</str>
|
Binary file
|
data/solr/solr/lib/localsolr.jar
CHANGED
Binary file
|
@@ -66,6 +66,11 @@ describe 'indexing attribute fields', :type => :indexer do
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
it 'should index latitude and longitude from a block' do
|
70
|
+
session.index(Photo.new(:lat => 30, :lng => -60))
|
71
|
+
connection.should have_add_with(:lat => 30, :long => -60)
|
72
|
+
end
|
73
|
+
|
69
74
|
it 'should correctly index an attribute field with block access' do
|
70
75
|
session.index(post(:title => 'The Blog Post'))
|
71
76
|
connection.should have_add_with(:sort_title_s => 'blog post')
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
1
3
|
describe 'faceting' do
|
2
4
|
describe 'on fields' do
|
3
5
|
it 'does not turn faceting on if no facet requested' do
|
@@ -75,6 +77,28 @@ describe 'faceting' do
|
|
75
77
|
end
|
76
78
|
connection.should have_last_search_with(:"f.category_ids_im.facet.mincount" => 1)
|
77
79
|
end
|
80
|
+
|
81
|
+
it 'sends a query facet for :any extra' do
|
82
|
+
session.search Post do
|
83
|
+
facet :category_ids, :extra => :any
|
84
|
+
end
|
85
|
+
connection.should have_last_search_with(:"facet.query" => "category_ids_im:[* TO *]")
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'sends a query facet for :none extra' do
|
89
|
+
session.search Post do
|
90
|
+
facet :category_ids, :extra => :none
|
91
|
+
end
|
92
|
+
connection.should have_last_search_with(:"facet.query" => "-category_ids_im:[* TO *]")
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'raises an ArgumentError if bogus extra is passed' do
|
96
|
+
lambda do
|
97
|
+
session.search Post do
|
98
|
+
facet :category_ids, :extra => :bogus
|
99
|
+
end
|
100
|
+
end.should raise_error(ArgumentError)
|
101
|
+
end
|
78
102
|
end
|
79
103
|
|
80
104
|
describe 'on time ranges' do
|
@@ -70,6 +70,15 @@ describe 'fulltext query', :type => :query do
|
|
70
70
|
connection.searches.last[:qf].split(' ').sort.should == %w(body_texts title_text)
|
71
71
|
end
|
72
72
|
|
73
|
+
it 'excludes text fields when instructed' do
|
74
|
+
session.search Post do
|
75
|
+
keywords 'keyword search' do
|
76
|
+
exclude_fields :backwards_title
|
77
|
+
end
|
78
|
+
end
|
79
|
+
connection.searches.last[:qf].split(' ').sort.should == %w(body_texts title_text)
|
80
|
+
end
|
81
|
+
|
73
82
|
it 'assigns boost to fields when specified' do
|
74
83
|
session.search Post do
|
75
84
|
keywords 'keyword search' do
|
@@ -124,6 +133,15 @@ describe 'fulltext query', :type => :query do
|
|
124
133
|
connection.should have_last_search_with(:pf => 'title_text^1.5')
|
125
134
|
end
|
126
135
|
|
136
|
+
it 'sets phrase slop from DSL' do
|
137
|
+
session.search Post do
|
138
|
+
keywords 'great pizza' do
|
139
|
+
phrase_slop 2
|
140
|
+
end
|
141
|
+
end
|
142
|
+
connection.should have_last_search_with(:ps => 2)
|
143
|
+
end
|
144
|
+
|
127
145
|
it 'sets boost for certain fields without restricting fields' do
|
128
146
|
session.search Post do
|
129
147
|
keywords 'great pizza' do
|
@@ -173,7 +191,68 @@ describe 'fulltext query', :type => :query do
|
|
173
191
|
end
|
174
192
|
end
|
175
193
|
end
|
176
|
-
connection.should have_last_search_with(:bq => 'average_rating_f:[2\.0 TO *]^2.0')
|
194
|
+
connection.should have_last_search_with(:bq => ['average_rating_f:[2\.0 TO *]^2.0'])
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'creates multiple boost queries' do
|
198
|
+
session.search Post do
|
199
|
+
keywords 'great pizza' do
|
200
|
+
boost(2.0) do
|
201
|
+
with(:average_rating).greater_than(2.0)
|
202
|
+
end
|
203
|
+
boost(1.5) do
|
204
|
+
with(:featured, true)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
connection.should have_last_search_with(
|
209
|
+
:bq => [
|
210
|
+
'average_rating_f:[2\.0 TO *]^2.0',
|
211
|
+
'featured_b:true^1.5'
|
212
|
+
]
|
213
|
+
)
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'sends minimum match parameter from options' do
|
217
|
+
session.search Post do
|
218
|
+
keywords 'great pizza', :minimum_match => 2
|
219
|
+
end
|
220
|
+
connection.should have_last_search_with(:mm => 2)
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'sends minimum match parameter from DSL' do
|
224
|
+
session.search Post do
|
225
|
+
keywords('great pizza') { minimum_match(2) }
|
226
|
+
end
|
227
|
+
connection.should have_last_search_with(:mm => 2)
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'sends tiebreaker parameter from options' do
|
231
|
+
session.search Post do
|
232
|
+
keywords 'great pizza', :tie => 0.1
|
233
|
+
end
|
234
|
+
connection.should have_last_search_with(:tie => 0.1)
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'sends tiebreaker parameter from DSL' do
|
238
|
+
session.search Post do
|
239
|
+
keywords('great pizza') { tie(0.1) }
|
240
|
+
end
|
241
|
+
connection.should have_last_search_with(:tie => 0.1)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'sends query phrase slop from options' do
|
245
|
+
session.search Post do
|
246
|
+
keywords 'great pizza', :query_phrase_slop => 2
|
247
|
+
end
|
248
|
+
connection.should have_last_search_with(:qs => 2)
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'sends query phrase slop from DSL' do
|
252
|
+
session.search Post do
|
253
|
+
keywords('great pizza') { query_phrase_slop(2) }
|
254
|
+
end
|
255
|
+
connection.should have_last_search_with(:qs => 2)
|
177
256
|
end
|
178
257
|
|
179
258
|
it 'allows specification of a text field that only exists in one type' do
|
@@ -77,15 +77,24 @@ describe 'highlighted fulltext queries', :type => :query do
|
|
77
77
|
)
|
78
78
|
end
|
79
79
|
|
80
|
-
it 'should set
|
80
|
+
it 'should set highlight fields from DSL' do
|
81
81
|
session.search(Post) do
|
82
82
|
keywords 'test' do
|
83
|
-
highlight :title
|
83
|
+
highlight :title
|
84
84
|
end
|
85
85
|
end
|
86
86
|
connection.should have_last_search_with(
|
87
|
-
:"hl.fl"
|
88
|
-
|
87
|
+
:"hl.fl" => %w(title_text)
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should not set formatting params specific to fields if fields specified' do
|
92
|
+
session.search(Post) do
|
93
|
+
keywords 'test', :highlight => :body
|
94
|
+
end
|
95
|
+
connection.should have_last_search_with(
|
96
|
+
:"hl.simple.pre" => '@@@hl@@@',
|
97
|
+
:"hl.simple.post" => '@@@endhl@@@'
|
89
98
|
)
|
90
99
|
end
|
91
100
|
|
@@ -100,6 +109,18 @@ describe 'highlighted fulltext queries', :type => :query do
|
|
100
109
|
)
|
101
110
|
end
|
102
111
|
|
112
|
+
it 'should set max snippets specific to highlight fields' do
|
113
|
+
session.search(Post) do
|
114
|
+
keywords 'test' do
|
115
|
+
highlight :title, :max_snippets => 3
|
116
|
+
end
|
117
|
+
end
|
118
|
+
connection.should have_last_search_with(
|
119
|
+
:"hl.fl" => %w(title_text),
|
120
|
+
:"f.title_text.hl.snippets" => 3
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
103
124
|
it 'should set the maximum size' do
|
104
125
|
session.search(Post) do
|
105
126
|
keywords 'text' do
|
@@ -111,7 +132,18 @@ describe 'highlighted fulltext queries', :type => :query do
|
|
111
132
|
)
|
112
133
|
end
|
113
134
|
|
114
|
-
it '
|
135
|
+
it 'should set the maximum size for specific fields' do
|
136
|
+
session.search(Post) do
|
137
|
+
keywords 'text' do
|
138
|
+
highlight :title, :fragment_size => 200
|
139
|
+
end
|
140
|
+
end
|
141
|
+
connection.should have_last_search_with(
|
142
|
+
:"f.title_text.hl.fragsize" => 200
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'enables merging of contiguous fragments' do
|
115
147
|
session.search(Post) do
|
116
148
|
keywords 'test' do
|
117
149
|
highlight :merge_contiguous_fragments => true
|
@@ -122,7 +154,18 @@ describe 'highlighted fulltext queries', :type => :query do
|
|
122
154
|
)
|
123
155
|
end
|
124
156
|
|
125
|
-
it 'enables
|
157
|
+
it 'enables merging of contiguous fragments for specific fields' do
|
158
|
+
session.search(Post) do
|
159
|
+
keywords 'test' do
|
160
|
+
highlight :title, :merge_contiguous_fragments => true
|
161
|
+
end
|
162
|
+
end
|
163
|
+
connection.should have_last_search_with(
|
164
|
+
:"f.title_text.hl.mergeContiguous" => 'true'
|
165
|
+
)
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'enables use of phrase highlighter' do
|
126
169
|
session.search(Post) do
|
127
170
|
keywords 'test' do
|
128
171
|
highlight :phrase_highlighter => true
|
@@ -133,6 +176,17 @@ describe 'highlighted fulltext queries', :type => :query do
|
|
133
176
|
)
|
134
177
|
end
|
135
178
|
|
179
|
+
it 'enables use of phrase highlighter for specific fields' do
|
180
|
+
session.search(Post) do
|
181
|
+
keywords 'test' do
|
182
|
+
highlight :title, :phrase_highlighter => true
|
183
|
+
end
|
184
|
+
end
|
185
|
+
connection.should have_last_search_with(
|
186
|
+
:"f.title_text.hl.usePhraseHighlighter" => 'true'
|
187
|
+
)
|
188
|
+
end
|
189
|
+
|
136
190
|
it 'requires field match if requested' do
|
137
191
|
session.search(Post) do
|
138
192
|
keywords 'test' do
|
@@ -144,4 +198,28 @@ describe 'highlighted fulltext queries', :type => :query do
|
|
144
198
|
)
|
145
199
|
end
|
146
200
|
|
201
|
+
it 'requires field match for specified field if requested' do
|
202
|
+
session.search(Post) do
|
203
|
+
keywords 'test' do
|
204
|
+
highlight :title, :phrase_highlighter => true, :require_field_match => true
|
205
|
+
end
|
206
|
+
end
|
207
|
+
connection.should have_last_search_with(
|
208
|
+
:"f.title_text.hl.requireFieldMatch" => 'true'
|
209
|
+
)
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'sets field specific params for different fields if different params given' do
|
213
|
+
session.search(Post) do
|
214
|
+
keywords 'test' do
|
215
|
+
highlight :title, :max_snippets => 2
|
216
|
+
highlight :body, :max_snippets => 1
|
217
|
+
end
|
218
|
+
end
|
219
|
+
connection.should have_last_search_with(
|
220
|
+
:"hl.fl" => %w(title_text body_texts),
|
221
|
+
:"f.title_text.hl.snippets" => 2,
|
222
|
+
:"f.body_texts.hl.snippets" => 1
|
223
|
+
)
|
224
|
+
end
|
147
225
|
end
|
@@ -81,6 +81,26 @@ describe 'faceting', :type => :search do
|
|
81
81
|
facet_values(result, :class).should == [Post, Namespaced::Comment]
|
82
82
|
end
|
83
83
|
|
84
|
+
it 'should return special :any facet' do
|
85
|
+
stub_query_facet(
|
86
|
+
'category_ids_im:[* TO *]' => 3
|
87
|
+
)
|
88
|
+
search = session.search(Post) { facet(:category_ids, :extra => :any) }
|
89
|
+
row = search.facet(:category_ids).rows.first
|
90
|
+
row.value.should == :any
|
91
|
+
row.count.should == 3
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should return special :none facet' do
|
95
|
+
stub_query_facet(
|
96
|
+
'-category_ids_im:[* TO *]' => 3
|
97
|
+
)
|
98
|
+
search = session.search(Post) { facet(:category_ids, :extra => :none) }
|
99
|
+
row = search.facet(:category_ids).rows.first
|
100
|
+
row.value.should == :none
|
101
|
+
row.count.should == 3
|
102
|
+
end
|
103
|
+
|
84
104
|
it 'should return date range facet' do
|
85
105
|
stub_date_facet(:published_at_d, 60*60*24, '2009-07-08T04:00:00Z' => 2, '2009-07-07T04:00:00Z' => 1)
|
86
106
|
start_time = Time.utc(2009, 7, 7, 4)
|
@@ -91,6 +111,16 @@ describe 'faceting', :type => :search do
|
|
91
111
|
facet.rows.last.value.should == ((start_time+24*60*60)..end_time)
|
92
112
|
end
|
93
113
|
|
114
|
+
it 'should return date range facet sorted by count' do
|
115
|
+
stub_date_facet(:published_at_d, 60*60*24, '2009-07-08T04:00:00Z' => 2, '2009-07-07T04:00:00Z' => 1)
|
116
|
+
start_time = Time.utc(2009, 7, 7, 4)
|
117
|
+
end_time = start_time + 2*24*60*60
|
118
|
+
result = session.search(Post) { facet(:published_at, :time_range => start_time..end_time, :sort => :count) }
|
119
|
+
facet = result.facet(:published_at)
|
120
|
+
facet.rows.first.value.should == ((start_time+24*60*60)..end_time)
|
121
|
+
facet.rows.last.value.should == (start_time..(start_time+24*60*60))
|
122
|
+
end
|
123
|
+
|
94
124
|
it 'returns query facet' do
|
95
125
|
stub_query_facet(
|
96
126
|
'average_rating_f:[3\.0 TO 5\.0]' => 3,
|
@@ -118,22 +148,28 @@ describe 'faceting', :type => :search do
|
|
118
148
|
session.search(Post) do
|
119
149
|
facet :average_rating, options do
|
120
150
|
row(1) { with(:average_rating, 1.0..2.0) }
|
121
|
-
row(2) { with(:average_rating, 2.0..3.0) }
|
122
151
|
row(3) { with(:average_rating, 3.0..4.0) }
|
152
|
+
row(2) { with(:average_rating, 2.0..3.0) }
|
153
|
+
row(4) { with(:average_rating, 4.0..5.0) }
|
123
154
|
end
|
124
155
|
end.facet(:average_rating).rows.map { |row| row.value }
|
125
156
|
end
|
126
157
|
|
127
158
|
before :each do
|
128
159
|
stub_query_facet(
|
129
|
-
'average_rating_f:[1\.0 TO 2\.0]' =>
|
130
|
-
'average_rating_f:[2\.0 TO 3\.0]' =>
|
131
|
-
'average_rating_f:[3\.0 TO 4\.0]' =>
|
160
|
+
'average_rating_f:[1\.0 TO 2\.0]' => 2,
|
161
|
+
'average_rating_f:[2\.0 TO 3\.0]' => 3,
|
162
|
+
'average_rating_f:[3\.0 TO 4\.0]' => 1,
|
163
|
+
'average_rating_f:[4\.0 TO 5\.0]' => 0
|
132
164
|
)
|
133
165
|
end
|
134
166
|
|
135
|
-
it 'sorts
|
136
|
-
facet_values_from_options.should == [1, 2]
|
167
|
+
it 'sorts in order of specification if no limit is given' do
|
168
|
+
facet_values_from_options.should == [1, 3, 2]
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'sorts lexically if lexical option is specified' do
|
172
|
+
facet_values_from_options(:sort => :index).should == [1, 2, 3]
|
137
173
|
end
|
138
174
|
|
139
175
|
it 'sorts by count by default if limit is given' do
|
@@ -141,7 +177,7 @@ describe 'faceting', :type => :search do
|
|
141
177
|
end
|
142
178
|
|
143
179
|
it 'sorts by count if count option is specified' do
|
144
|
-
facet_values_from_options(:sort => :count).should == [2, 1]
|
180
|
+
facet_values_from_options(:sort => :count).should == [2, 1, 3]
|
145
181
|
end
|
146
182
|
|
147
183
|
it 'sorts lexically if lexical option is specified even if limit is given' do
|
@@ -153,11 +189,11 @@ describe 'faceting', :type => :search do
|
|
153
189
|
end
|
154
190
|
|
155
191
|
it 'allows zero count if specified' do
|
156
|
-
facet_values_from_options(:zeros => true).should == [1, 2,
|
192
|
+
facet_values_from_options(:zeros => true).should == [1, 3, 2, 4]
|
157
193
|
end
|
158
194
|
|
159
195
|
it 'sets minimum count' do
|
160
|
-
facet_values_from_options(:minimum_count => 2).should == [2]
|
196
|
+
facet_values_from_options(:minimum_count => 2).should == [1, 2]
|
161
197
|
end
|
162
198
|
end
|
163
199
|
|
@@ -21,8 +21,8 @@ describe 'search with highlighting results', :type => :search do
|
|
21
21
|
@search.hits.last.should have(2).highlights(:body)
|
22
22
|
end
|
23
23
|
|
24
|
-
it 'returns
|
25
|
-
@search.hits.first.highlights(:body).should
|
24
|
+
it 'returns an empty array if a given field does not have a highlight' do
|
25
|
+
@search.hits.first.highlights(:body).should == []
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'should format hits with <em> by default' do
|
@@ -44,6 +44,11 @@ describe 'hits', :type => :search do
|
|
44
44
|
session.search(Post, Namespaced::Comment).hits.first.stored(:title).should == 'Title'
|
45
45
|
end
|
46
46
|
|
47
|
+
it 'should return stored text fields' do
|
48
|
+
stub_full_results('instance' => Post.new, 'body_texts' => 'Body')
|
49
|
+
session.search(Post, Namespaced::Comment).hits.first.stored(:body).should == 'Body'
|
50
|
+
end
|
51
|
+
|
47
52
|
it 'should typecast stored field values in hits' do
|
48
53
|
time = Time.utc(2008, 7, 8, 2, 45)
|
49
54
|
stub_full_results('instance' => Post.new, 'last_indexed_at_ds' => time.xmlschema)
|
@@ -46,6 +46,7 @@ describe 'search faceting' do
|
|
46
46
|
facet_values.each_with_index do |value, i|
|
47
47
|
i.times { Sunspot.index(Post.new(:title => value, :blog_id => 1)) }
|
48
48
|
end
|
49
|
+
Sunspot.index(Post.new(:blog_id => 1))
|
49
50
|
Sunspot.index(Post.new(:title => 'zero', :blog_id => 2))
|
50
51
|
Sunspot.commit
|
51
52
|
end
|
@@ -96,6 +97,24 @@ describe 'search faceting' do
|
|
96
97
|
end
|
97
98
|
search.facet(:title).rows.map { |row| row.value }.should == %w(four three two one)
|
98
99
|
end
|
100
|
+
|
101
|
+
it 'should return :all facet' do
|
102
|
+
search = Sunspot.search(Post) do
|
103
|
+
with :blog_id, 1
|
104
|
+
facet :title, :extra => :any
|
105
|
+
end
|
106
|
+
search.facet(:title).rows.first.value.should == :any
|
107
|
+
search.facet(:title).rows.first.count.should == 10
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should return :none facet' do
|
111
|
+
search = Sunspot.search(Post) do
|
112
|
+
with :blog_id, 1
|
113
|
+
facet :title, :extra => :none
|
114
|
+
end
|
115
|
+
search.facet(:title).rows.first.value.should == :none
|
116
|
+
search.facet(:title).rows.first.count.should == 1
|
117
|
+
end
|
99
118
|
end
|
100
119
|
|
101
120
|
context 'date facets' do
|