sunspot 1.0.5 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -0
- data/TODO +6 -5
- data/bin/sunspot-solr +4 -0
- data/installer/config/schema.yml +24 -0
- data/lib/sunspot/composite_setup.rb +14 -0
- data/lib/sunspot/dsl/adjustable.rb +47 -0
- data/lib/sunspot/dsl/fulltext.rb +23 -8
- data/lib/sunspot/dsl/function.rb +14 -0
- data/lib/sunspot/dsl/functional.rb +41 -0
- data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
- data/lib/sunspot/dsl/paginatable.rb +28 -0
- data/lib/sunspot/dsl/search.rb +1 -1
- data/lib/sunspot/dsl/{query.rb → standard_query.rb} +4 -49
- data/lib/sunspot/dsl.rb +3 -2
- data/lib/sunspot/field.rb +16 -2
- data/lib/sunspot/indexer.rb +1 -1
- data/lib/sunspot/installer/schema_builder.rb +1 -1
- data/lib/sunspot/installer/solrconfig_updater.rb +13 -0
- data/lib/sunspot/installer/task_helper.rb +1 -1
- data/lib/sunspot/query/abstract_field_facet.rb +5 -0
- data/lib/sunspot/query/boost_query.rb +5 -1
- data/lib/sunspot/query/{query.rb → common_query.rb} +26 -20
- data/lib/sunspot/query/composite_fulltext.rb +31 -0
- data/lib/sunspot/query/dismax.rb +45 -6
- data/lib/sunspot/query/function_query.rb +52 -0
- data/lib/sunspot/query/more_like_this.rb +60 -0
- data/lib/sunspot/query/more_like_this_query.rb +12 -0
- data/lib/sunspot/query/standard_query.rb +20 -0
- data/lib/sunspot/query/text_field_boost.rb +2 -0
- data/lib/sunspot/query.rb +3 -2
- data/lib/sunspot/search/abstract_search.rb +302 -0
- data/lib/sunspot/search/date_facet.rb +1 -1
- data/lib/sunspot/search/facet_row.rb +1 -1
- data/lib/sunspot/search/field_facet.rb +1 -1
- data/lib/sunspot/search/highlight.rb +1 -1
- data/lib/sunspot/search/hit.rb +1 -1
- data/lib/sunspot/search/more_like_this_search.rb +31 -0
- data/lib/sunspot/search/query_facet.rb +1 -1
- data/lib/sunspot/search/standard_search.rb +21 -0
- data/lib/sunspot/search.rb +3 -288
- data/lib/sunspot/server.rb +8 -4
- data/lib/sunspot/session.rb +30 -2
- data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +1 -1
- data/lib/sunspot/session_proxy/sharding_session_proxy.rb +9 -0
- data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +9 -2
- data/lib/sunspot/setup.rb +32 -3
- data/lib/sunspot/type.rb +74 -0
- data/lib/sunspot/util.rb +3 -2
- data/lib/sunspot/version.rb +1 -1
- data/lib/sunspot.rb +9 -1
- data/solr/solr/conf/schema.xml +12 -0
- data/solr/solr/conf/solrconfig.xml +6 -0
- data/spec/api/indexer/attributes_spec.rb +9 -3
- data/spec/api/indexer/fulltext_spec.rb +2 -2
- data/spec/api/indexer/removal_spec.rb +1 -1
- data/spec/api/query/advanced_manipulation_examples.rb +35 -0
- data/spec/api/query/{connectives_spec.rb → connectives_examples.rb} +19 -19
- data/spec/api/query/{dynamic_fields_spec.rb → dynamic_fields_examples.rb} +33 -17
- data/spec/api/query/{faceting_spec.rb → faceting_examples.rb} +146 -43
- data/spec/api/query/{fulltext_spec.rb → fulltext_examples.rb} +81 -47
- data/spec/api/query/function_spec.rb +70 -0
- data/spec/api/query/{highlighting_spec.rb → highlighting_examples.rb} +27 -27
- data/spec/api/query/{local_spec.rb → local_examples.rb} +5 -5
- data/spec/api/query/more_like_this_spec.rb +140 -0
- data/spec/api/query/{ordering_pagination_spec.rb → ordering_pagination_examples.rb} +16 -16
- data/spec/api/query/{scope_spec.rb → scope_examples.rb} +44 -61
- data/spec/api/query/standard_spec.rb +28 -0
- data/spec/api/query/{text_field_scoping_spec.rb → text_field_scoping_examples.rb} +5 -5
- data/spec/api/search/dynamic_fields_spec.rb +6 -0
- data/spec/api/search/faceting_spec.rb +10 -10
- data/spec/api/search/hits_spec.rb +1 -1
- data/spec/api/search/results_spec.rb +10 -0
- data/spec/api/server_spec.rb +6 -0
- data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +2 -2
- data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +17 -0
- data/spec/api/spec_helper.rb +2 -0
- data/spec/helpers/query_helper.rb +25 -0
- data/spec/helpers/search_helper.rb +4 -0
- data/spec/integration/faceting_spec.rb +8 -0
- data/spec/integration/keyword_search_spec.rb +75 -3
- data/spec/integration/local_search_spec.rb +1 -1
- data/spec/integration/more_like_this_spec.rb +43 -0
- data/spec/mocks/comment.rb +1 -1
- data/spec/mocks/connection.rb +27 -12
- data/spec/mocks/post.rb +5 -4
- data/spec/spec_helper.rb +4 -21
- data/tasks/gemspec.rake +1 -1
- metadata +39 -27
- data/spec/api/query/adjust_params_spec.rb +0 -37
- data/spec/api/query/facet_local_params_spec.rb +0 -103
data/lib/sunspot/type.rb
CHANGED
@@ -17,6 +17,46 @@ module Sunspot
|
|
17
17
|
# Ruby type.
|
18
18
|
#
|
19
19
|
module Type
|
20
|
+
class <<self
|
21
|
+
def register(sunspot_type, *classes)
|
22
|
+
classes.each do |clazz|
|
23
|
+
ruby_type_map[clazz.name.to_sym] = sunspot_type.instance
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def for_class(clazz)
|
28
|
+
if clazz
|
29
|
+
ruby_type_map[clazz.name.to_sym] || for_class(clazz.superclass)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def for(object)
|
34
|
+
for_class(object.class)
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_indexed(object)
|
38
|
+
if type = self.for(object)
|
39
|
+
type.to_indexed(object)
|
40
|
+
else
|
41
|
+
object.to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_literal(object)
|
46
|
+
if type = self.for(object)
|
47
|
+
type.to_literal(object)
|
48
|
+
else
|
49
|
+
raise ArgumentError, "Can't use #{object.inspect} as Solr literal: #{object.class} has no registered Solr type"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def ruby_type_map
|
56
|
+
@ruby_type_map ||= {}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
20
60
|
class AbstractType #:nodoc:
|
21
61
|
class <<self
|
22
62
|
def instance
|
@@ -28,6 +68,17 @@ module Sunspot
|
|
28
68
|
def accepts_dynamic?
|
29
69
|
true
|
30
70
|
end
|
71
|
+
|
72
|
+
def accepts_more_like_this?
|
73
|
+
false
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_literal(object)
|
77
|
+
raise(
|
78
|
+
ArgumentError,
|
79
|
+
"#{self.class.name} cannot be used as a Solr literal"
|
80
|
+
)
|
81
|
+
end
|
31
82
|
end
|
32
83
|
|
33
84
|
#
|
@@ -53,6 +104,10 @@ module Sunspot
|
|
53
104
|
def accepts_dynamic?
|
54
105
|
false
|
55
106
|
end
|
107
|
+
|
108
|
+
def accepts_more_like_this?
|
109
|
+
true
|
110
|
+
end
|
56
111
|
end
|
57
112
|
|
58
113
|
#
|
@@ -71,6 +126,7 @@ module Sunspot
|
|
71
126
|
string
|
72
127
|
end
|
73
128
|
end
|
129
|
+
register(StringType, String)
|
74
130
|
|
75
131
|
#
|
76
132
|
# The Integer type represents integers.
|
@@ -84,10 +140,15 @@ module Sunspot
|
|
84
140
|
value.to_i.to_s if value
|
85
141
|
end
|
86
142
|
|
143
|
+
def to_literal(value)
|
144
|
+
to_indexed(value)
|
145
|
+
end
|
146
|
+
|
87
147
|
def cast(string) #:nodoc:
|
88
148
|
string.to_i
|
89
149
|
end
|
90
150
|
end
|
151
|
+
register(IntegerType, Integer)
|
91
152
|
|
92
153
|
#
|
93
154
|
# The Long type indexes Ruby Fixnum and Bignum numbers into Java Longs
|
@@ -110,10 +171,15 @@ module Sunspot
|
|
110
171
|
value.to_f.to_s if value
|
111
172
|
end
|
112
173
|
|
174
|
+
def to_literal(value)
|
175
|
+
to_indexed(value)
|
176
|
+
end
|
177
|
+
|
113
178
|
def cast(string) #:nodoc:
|
114
179
|
string.to_f
|
115
180
|
end
|
116
181
|
end
|
182
|
+
register(FloatType, Float)
|
117
183
|
|
118
184
|
#
|
119
185
|
# The Double type indexes Ruby Floats (which are in fact doubles) into Java
|
@@ -142,6 +208,10 @@ module Sunspot
|
|
142
208
|
end
|
143
209
|
end
|
144
210
|
|
211
|
+
def to_literal(value)
|
212
|
+
to_indexed(value)
|
213
|
+
end
|
214
|
+
|
145
215
|
def cast(string) #:nodoc:
|
146
216
|
begin
|
147
217
|
Time.xmlschema(string)
|
@@ -166,6 +236,7 @@ module Sunspot
|
|
166
236
|
end
|
167
237
|
end
|
168
238
|
end
|
239
|
+
register TimeType, Time, DateTime
|
169
240
|
|
170
241
|
#
|
171
242
|
# The DateType encapsulates dates (without time information). Internally,
|
@@ -192,6 +263,7 @@ module Sunspot
|
|
192
263
|
Date.civil(time.year, time.mon, time.mday)
|
193
264
|
end
|
194
265
|
end
|
266
|
+
register DateType, Date
|
195
267
|
|
196
268
|
#
|
197
269
|
# Store integers in a TrieField, which makes range queries much faster.
|
@@ -248,6 +320,7 @@ module Sunspot
|
|
248
320
|
end
|
249
321
|
end
|
250
322
|
end
|
323
|
+
register BooleanType, TrueClass, FalseClass
|
251
324
|
|
252
325
|
class ClassType < AbstractType
|
253
326
|
def indexed_name(name) #:nodoc:
|
@@ -262,5 +335,6 @@ module Sunspot
|
|
262
335
|
Sunspot::Util.full_const_get(string)
|
263
336
|
end
|
264
337
|
end
|
338
|
+
register ClassType, Class
|
265
339
|
end
|
266
340
|
end
|
data/lib/sunspot/util.rb
CHANGED
@@ -100,7 +100,8 @@ module Sunspot
|
|
100
100
|
# as I know the behavior of Kernel.Array() is otherwise fine.
|
101
101
|
#
|
102
102
|
def Array(object)
|
103
|
-
|
103
|
+
case object
|
104
|
+
when String, Hash
|
104
105
|
[object]
|
105
106
|
else
|
106
107
|
super
|
@@ -164,7 +165,7 @@ module Sunspot
|
|
164
165
|
#
|
165
166
|
def deep_merge_into(destination, left, right)
|
166
167
|
left.each_pair do |name, left_value|
|
167
|
-
right_value = right[name]
|
168
|
+
right_value = right[name] if right
|
168
169
|
destination[name] =
|
169
170
|
if right_value.nil? || left_value == right_value
|
170
171
|
left_value
|
data/lib/sunspot/version.rb
CHANGED
data/lib/sunspot.rb
CHANGED
@@ -243,7 +243,7 @@ module Sunspot
|
|
243
243
|
#
|
244
244
|
# Sunspot::Search::
|
245
245
|
# Search object, not yet executed. Query parameters can be added manually;
|
246
|
-
# then #execute
|
246
|
+
# then #execute should be called.
|
247
247
|
#
|
248
248
|
def new_search(*types, &block)
|
249
249
|
session.new_search(*types, &block)
|
@@ -323,6 +323,14 @@ module Sunspot
|
|
323
323
|
session.search(*types, &block)
|
324
324
|
end
|
325
325
|
|
326
|
+
def new_more_like_this(object, *types, &block)
|
327
|
+
session.new_more_like_this(object, *types, &block)
|
328
|
+
end
|
329
|
+
|
330
|
+
def more_like_this(object, *types, &block)
|
331
|
+
session.more_like_this(object, *types, &block)
|
332
|
+
end
|
333
|
+
|
326
334
|
# Remove objects from the index. Any time an object is destroyed, it must
|
327
335
|
# be removed from the index; otherwise, the index will contain broken
|
328
336
|
# references to objects that do not exist, which will cause errors when
|
data/solr/solr/conf/schema.xml
CHANGED
@@ -211,6 +211,18 @@
|
|
211
211
|
<dynamicField name="*_dts" stored="true" type="tdate" multiValued="false" indexed="true"/>
|
212
212
|
<!-- *** This dynamicField is used by Sunspot! *** -->
|
213
213
|
<dynamicField name="*_dtms" stored="true" type="tdate" multiValued="true" indexed="true"/>
|
214
|
+
<!-- *** This dynamicField is used by Sunspot! *** -->
|
215
|
+
<dynamicField name="*_textv" stored="false" termVectors="true" type="text" multiValued="true" indexed="true"/>
|
216
|
+
<!-- *** This dynamicField is used by Sunspot! *** -->
|
217
|
+
<dynamicField name="*_textsv" stored="true" termVectors="true" type="text" multiValued="true" indexed="true"/>
|
218
|
+
<!-- *** This dynamicField is used by Sunspot! *** -->
|
219
|
+
<dynamicField name="*_et" stored="false" termVectors="true" type="tdouble" multiValued="false" indexed="true"/>
|
220
|
+
<!-- *** This dynamicField is used by Sunspot! *** -->
|
221
|
+
<dynamicField name="*_etm" stored="false" termVectors="true" type="tdouble" multiValued="true" indexed="true"/>
|
222
|
+
<!-- *** This dynamicField is used by Sunspot! *** -->
|
223
|
+
<dynamicField name="*_ets" stored="true" termVectors="true" type="tdouble" multiValued="false" indexed="true"/>
|
224
|
+
<!-- *** This dynamicField is used by Sunspot! *** -->
|
225
|
+
<dynamicField name="*_etms" stored="true" termVectors="true" type="tdouble" multiValued="true" indexed="true"/>
|
214
226
|
</fields>
|
215
227
|
<!-- Field to use to determine and enforce document uniqueness.
|
216
228
|
Unless this field is marked with required="false", it will be a required field
|
@@ -929,4 +929,10 @@
|
|
929
929
|
-->
|
930
930
|
</admin>
|
931
931
|
<searchComponent name="spatial" class="me.outofti.solrspatiallight.SpatialQueryComponent"/>
|
932
|
+
<requestHandler class="solr.MoreLikeThisHandler" name="/mlt">
|
933
|
+
<lst name="defaults">
|
934
|
+
<str name="mlt.mintf">1</str>
|
935
|
+
<str name="mlt.mindf">2</str>
|
936
|
+
</lst>
|
937
|
+
</requestHandler>
|
932
938
|
</config>
|
@@ -18,7 +18,7 @@ describe 'indexing attribute fields', :type => :indexer do
|
|
18
18
|
|
19
19
|
it 'should correctly index a float attribute field' do
|
20
20
|
session.index(post(:ratings_average => 2.23))
|
21
|
-
connection.should have_add_with(:
|
21
|
+
connection.should have_add_with(:average_rating_ft => '2.23')
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'should correctly index a double attribute field' do
|
@@ -55,14 +55,14 @@ describe 'indexing attribute fields', :type => :indexer do
|
|
55
55
|
session.index(
|
56
56
|
post(:published_at => Time.parse('1983-07-08 05:00:00 -0400'))
|
57
57
|
)
|
58
|
-
connection.should have_add_with(:
|
58
|
+
connection.should have_add_with(:published_at_dt => '1983-07-08T09:00:00Z')
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'should correctly index a time field that\'s after 32-bit Y2K' do
|
62
62
|
session.index(
|
63
63
|
post(:published_at => DateTime.parse('2050-07-08 05:00:00 -0400'))
|
64
64
|
)
|
65
|
-
connection.should have_add_with(:
|
65
|
+
connection.should have_add_with(:published_at_dt => '2050-07-08T09:00:00Z')
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'should correctly index a date field' do
|
@@ -140,4 +140,10 @@ describe 'indexing attribute fields', :type => :indexer do
|
|
140
140
|
session.index(post(:author_name => ['Mat Brown', 'Matthew Brown']))
|
141
141
|
end.should raise_error(ArgumentError)
|
142
142
|
end
|
143
|
+
|
144
|
+
it 'should throw an ArgumentError if specifying more_like_this on type that does not support it' do
|
145
|
+
lambda do
|
146
|
+
Sunspot.setup(Post) { integer :popularity, :more_like_this => true }
|
147
|
+
end.should raise_error(ArgumentError)
|
148
|
+
end
|
143
149
|
end
|
@@ -8,7 +8,7 @@ describe 'indexing fulltext fields' do
|
|
8
8
|
|
9
9
|
it 'indexes stored text field' do
|
10
10
|
session.index(post(:body => 'Test body'))
|
11
|
-
connection.should have_add_with(:
|
11
|
+
connection.should have_add_with(:body_textsv => 'Test body')
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'indexes text field with boost' do
|
@@ -18,7 +18,7 @@ describe 'indexing fulltext fields' do
|
|
18
18
|
|
19
19
|
it 'indexes multiple values for a text field' do
|
20
20
|
session.index(post(:body => %w(some title)))
|
21
|
-
connection.should have_add_with(:
|
21
|
+
connection.should have_add_with(:body_textsv => %w(some title))
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'indexes text via a block accessor' do
|
@@ -25,7 +25,7 @@ describe 'document removal', :type => :indexer do
|
|
25
25
|
|
26
26
|
it 'removes everything from the index' do
|
27
27
|
session.remove_all
|
28
|
-
connection.should have_delete_by_query("
|
28
|
+
connection.should have_delete_by_query("*:*")
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'removes everything from the index and immediately commits' do
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
shared_examples_for "query with advanced manipulation" do
|
4
|
+
describe 'adjust_solr_params' do
|
5
|
+
before :each do
|
6
|
+
search do
|
7
|
+
adjust_solr_params do |params|
|
8
|
+
params[:rows] = 40
|
9
|
+
params[:qt] = 'complicated'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "modifies existing param" do
|
15
|
+
connection.should have_last_search_with(:rows => 40)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "adds new param" do
|
19
|
+
connection.should have_last_search_with(:qt => 'complicated')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'request_handler' do
|
24
|
+
before :each do
|
25
|
+
connection.expected_handler = :myRequestHandler
|
26
|
+
search do
|
27
|
+
request_handler :myRequestHandler
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should use specified request handler' do
|
32
|
+
connection.should have_last_search_with({})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
shared_examples_for "query with connective scope" do
|
2
2
|
it 'creates a disjunction between two restrictions' do
|
3
|
-
|
3
|
+
search do
|
4
4
|
any_of do
|
5
5
|
with :category_ids, 1
|
6
6
|
with :blog_id, 2
|
@@ -12,7 +12,7 @@ describe 'connective in scope', :type => :query do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'creates a conjunction inside of a disjunction' do
|
15
|
-
|
15
|
+
search do
|
16
16
|
any_of do
|
17
17
|
with :blog_id, 2
|
18
18
|
all_of do
|
@@ -23,12 +23,12 @@ describe 'connective in scope', :type => :query do
|
|
23
23
|
end
|
24
24
|
connection.should have_last_search_including(
|
25
25
|
:fq,
|
26
|
-
'(blog_id_i:2 OR (category_ids_im:1 AND
|
26
|
+
'(blog_id_i:2 OR (category_ids_im:1 AND average_rating_ft:[3\.0 TO *]))'
|
27
27
|
)
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'creates a disjunction with nested conjunction with negated restrictions' do
|
31
|
-
|
31
|
+
search do
|
32
32
|
any_of do
|
33
33
|
with :category_ids, 1
|
34
34
|
all_of do
|
@@ -38,12 +38,12 @@ describe 'connective in scope', :type => :query do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
connection.should have_last_search_including(
|
41
|
-
:fq, '(category_ids_im:1 OR (-
|
41
|
+
:fq, '(category_ids_im:1 OR (-average_rating_ft:[3\.0 TO *] AND blog_id_i:1))'
|
42
42
|
)
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'does nothing special if #all_of called from the top level' do
|
46
|
-
|
46
|
+
search do
|
47
47
|
all_of do
|
48
48
|
with :blog_id, 2
|
49
49
|
with :category_ids, 1
|
@@ -55,19 +55,19 @@ describe 'connective in scope', :type => :query do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'creates a disjunction with negated restrictions' do
|
58
|
-
|
58
|
+
search do
|
59
59
|
any_of do
|
60
60
|
with :category_ids, 1
|
61
61
|
without(:average_rating).greater_than(3.0)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
connection.should have_last_search_including(
|
65
|
-
:fq, '-(-category_ids_im:1 AND
|
65
|
+
:fq, '-(-category_ids_im:1 AND average_rating_ft:[3\.0 TO *])'
|
66
66
|
)
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'creates a disjunction with a negated restriction and a nested disjunction in a conjunction with a negated restriction' do
|
70
|
-
|
70
|
+
search do
|
71
71
|
any_of do
|
72
72
|
without(:title, 'Yes')
|
73
73
|
all_of do
|
@@ -80,11 +80,11 @@ describe 'connective in scope', :type => :query do
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
connection.should have_last_search_including(
|
83
|
-
:fq, '-(title_ss:Yes AND -(blog_id_i:1 AND -(-category_ids_im:4 AND
|
83
|
+
:fq, '-(title_ss:Yes AND -(blog_id_i:1 AND -(-category_ids_im:4 AND average_rating_ft:2\.0)))'
|
84
84
|
)
|
85
85
|
end
|
86
86
|
it 'creates a disjunction with nested conjunction with nested disjunction with negated restriction' do
|
87
|
-
|
87
|
+
search do
|
88
88
|
any_of do
|
89
89
|
with(:title, 'Yes')
|
90
90
|
all_of do
|
@@ -97,7 +97,7 @@ describe 'connective in scope', :type => :query do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
connection.should have_last_search_including(
|
100
|
-
:fq, '(title_ss:Yes OR (blog_id_i:1 AND -(-category_ids_im:4 AND
|
100
|
+
:fq, '(title_ss:Yes OR (blog_id_i:1 AND -(-category_ids_im:4 AND average_rating_ft:2\.0)))'
|
101
101
|
)
|
102
102
|
end
|
103
103
|
|
@@ -114,7 +114,7 @@ describe 'connective in scope', :type => :query do
|
|
114
114
|
# logical semantics of the disjunction.
|
115
115
|
#
|
116
116
|
it 'creates a single disjunction when disjunctions nested' do
|
117
|
-
|
117
|
+
search do
|
118
118
|
any_of do
|
119
119
|
with(:title, 'Yes')
|
120
120
|
any_of do
|
@@ -130,7 +130,7 @@ describe 'connective in scope', :type => :query do
|
|
130
130
|
|
131
131
|
it 'creates a disjunction with instance exclusion' do
|
132
132
|
post = Post.new
|
133
|
-
|
133
|
+
search do
|
134
134
|
any_of do
|
135
135
|
without(post)
|
136
136
|
with(:category_ids, 1)
|
@@ -142,19 +142,19 @@ describe 'connective in scope', :type => :query do
|
|
142
142
|
end
|
143
143
|
|
144
144
|
it 'creates a disjunction with empty restriction' do
|
145
|
-
|
145
|
+
search do
|
146
146
|
any_of do
|
147
147
|
with(:average_rating, nil)
|
148
148
|
with(:average_rating).greater_than(3.0)
|
149
149
|
end
|
150
150
|
end
|
151
151
|
connection.should have_last_search_including(
|
152
|
-
:fq, '-(
|
152
|
+
:fq, '-(average_rating_ft:[* TO *] AND -average_rating_ft:[3\.0 TO *])'
|
153
153
|
)
|
154
154
|
end
|
155
155
|
|
156
156
|
it 'creates a disjunction with some text field components' do
|
157
|
-
|
157
|
+
search do
|
158
158
|
any_of do
|
159
159
|
text_fields do
|
160
160
|
with(:title).starting_with('test')
|
@@ -168,7 +168,7 @@ describe 'connective in scope', :type => :query do
|
|
168
168
|
end
|
169
169
|
|
170
170
|
it 'should ignore empty connectives' do
|
171
|
-
|
171
|
+
search do
|
172
172
|
any_of {}
|
173
173
|
end
|
174
174
|
connection.should_not have_last_search_including(:fq, '')
|
@@ -1,8 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe 'dynamic field query', :type => :query do
|
1
|
+
shared_examples_for "query with dynamic field support" do
|
4
2
|
it 'restricts by dynamic string field with equality restriction' do
|
5
|
-
|
3
|
+
search do
|
6
4
|
dynamic :custom_string do
|
7
5
|
with :test, 'string'
|
8
6
|
end
|
@@ -11,7 +9,7 @@ describe 'dynamic field query', :type => :query do
|
|
11
9
|
end
|
12
10
|
|
13
11
|
it 'restricts by dynamic integer field with less than restriction' do
|
14
|
-
|
12
|
+
search do
|
15
13
|
dynamic :custom_integer do
|
16
14
|
with(:test).less_than(1)
|
17
15
|
end
|
@@ -20,7 +18,7 @@ describe 'dynamic field query', :type => :query do
|
|
20
18
|
end
|
21
19
|
|
22
20
|
it 'restricts by dynamic float field with between restriction' do
|
23
|
-
|
21
|
+
search do
|
24
22
|
dynamic :custom_float do
|
25
23
|
with(:test).between(2.2..3.3)
|
26
24
|
end
|
@@ -29,7 +27,7 @@ describe 'dynamic field query', :type => :query do
|
|
29
27
|
end
|
30
28
|
|
31
29
|
it 'restricts by dynamic time field with any of restriction' do
|
32
|
-
|
30
|
+
search do
|
33
31
|
dynamic :custom_time do
|
34
32
|
with(:test).any_of([Time.parse('2009-02-10 14:00:00 UTC'),
|
35
33
|
Time.parse('2009-02-13 18:00:00 UTC')])
|
@@ -39,7 +37,7 @@ describe 'dynamic field query', :type => :query do
|
|
39
37
|
end
|
40
38
|
|
41
39
|
it 'restricts by dynamic boolean field with equality restriction' do
|
42
|
-
|
40
|
+
search do
|
43
41
|
dynamic :custom_boolean do
|
44
42
|
with :test, false
|
45
43
|
end
|
@@ -48,7 +46,7 @@ describe 'dynamic field query', :type => :query do
|
|
48
46
|
end
|
49
47
|
|
50
48
|
it 'negates a dynamic field restriction' do
|
51
|
-
|
49
|
+
search do
|
52
50
|
dynamic :custom_string do
|
53
51
|
without :test, 'foo'
|
54
52
|
end
|
@@ -57,7 +55,7 @@ describe 'dynamic field query', :type => :query do
|
|
57
55
|
end
|
58
56
|
|
59
57
|
it 'scopes by a dynamic field inside a disjunction' do
|
60
|
-
|
58
|
+
search do
|
61
59
|
any_of do
|
62
60
|
dynamic :custom_string do
|
63
61
|
with :test, 'foo'
|
@@ -71,7 +69,7 @@ describe 'dynamic field query', :type => :query do
|
|
71
69
|
end
|
72
70
|
|
73
71
|
it 'orders by a dynamic field' do
|
74
|
-
|
72
|
+
search do
|
75
73
|
dynamic :custom_integer do
|
76
74
|
order_by :test, :desc
|
77
75
|
end
|
@@ -80,7 +78,7 @@ describe 'dynamic field query', :type => :query do
|
|
80
78
|
end
|
81
79
|
|
82
80
|
it 'orders by a dynamic field and static field, with given precedence' do
|
83
|
-
|
81
|
+
search do
|
84
82
|
dynamic :custom_integer do
|
85
83
|
order_by :test, :desc
|
86
84
|
end
|
@@ -91,7 +89,7 @@ describe 'dynamic field query', :type => :query do
|
|
91
89
|
|
92
90
|
it 'raises an UnrecognizedFieldError if an unknown dynamic field is searched by' do
|
93
91
|
lambda do
|
94
|
-
|
92
|
+
search do
|
95
93
|
dynamic(:bogus) { with :some, 'value' }
|
96
94
|
end
|
97
95
|
end.should raise_error(Sunspot::UnrecognizedFieldError)
|
@@ -99,7 +97,7 @@ describe 'dynamic field query', :type => :query do
|
|
99
97
|
|
100
98
|
it 'raises a NoMethodError if pagination is attempted in a dynamic query' do
|
101
99
|
lambda do
|
102
|
-
|
100
|
+
search do
|
103
101
|
dynamic :custom_string do
|
104
102
|
paginate :page => 3, :per_page => 10
|
105
103
|
end
|
@@ -107,8 +105,26 @@ describe 'dynamic field query', :type => :query do
|
|
107
105
|
end.should raise_error(NoMethodError)
|
108
106
|
end
|
109
107
|
|
108
|
+
it 'requests field facet on dynamic field' do
|
109
|
+
search do
|
110
|
+
dynamic :custom_string do
|
111
|
+
facet(:test)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
connection.should have_last_search_including(:"facet.field", 'custom_string:test_ss')
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'requests named field facet on dynamic field' do
|
118
|
+
search do
|
119
|
+
dynamic :custom_string do
|
120
|
+
facet(:test, :name => :bogus)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
connection.should have_last_search_including(:"facet.field", '{!key=bogus}custom_string:test_ss')
|
124
|
+
end
|
125
|
+
|
110
126
|
it 'requests query facet with internal dynamic field' do
|
111
|
-
|
127
|
+
search do
|
112
128
|
facet :test do
|
113
129
|
row 'foo' do
|
114
130
|
dynamic :custom_string do
|
@@ -123,7 +139,7 @@ describe 'dynamic field query', :type => :query do
|
|
123
139
|
end
|
124
140
|
|
125
141
|
it 'requests query facet with external dynamic field' do
|
126
|
-
|
142
|
+
search do
|
127
143
|
dynamic :custom_string do
|
128
144
|
facet :test do
|
129
145
|
row 'foo' do
|
@@ -139,7 +155,7 @@ describe 'dynamic field query', :type => :query do
|
|
139
155
|
end
|
140
156
|
|
141
157
|
it 'allows scoping on dynamic fields common to all types' do
|
142
|
-
|
158
|
+
search Post, Namespaced::Comment do
|
143
159
|
dynamic :custom_float do
|
144
160
|
with(:test, 1.23)
|
145
161
|
end
|