sunspot 1.0.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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/README.rdoc
CHANGED
|
@@ -230,6 +230,9 @@ Sunspot repository at `upstream`:
|
|
|
230
230
|
* Tom Coleman (tom@thesnail.org)
|
|
231
231
|
* Matt Mitchell (goodieboy@gmail.com)
|
|
232
232
|
* Nathan Beyer (nbeyer@gmail.com)
|
|
233
|
+
* Kieran Topping
|
|
234
|
+
* Nicolas Braem (nicolas.braem@gmail.com)
|
|
235
|
+
* Jeremy Ashkenas (jashkenas@gmail.com)
|
|
233
236
|
|
|
234
237
|
== License
|
|
235
238
|
|
data/TODO
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
=== Sunspot 1.
|
|
2
|
-
*
|
|
1
|
+
=== Sunspot 1.1.x ===
|
|
2
|
+
* commitWithin (needs support from RSolr, currently available in master)
|
|
3
|
+
* commit options (non-blocking, etc.)
|
|
3
4
|
|
|
4
|
-
===
|
|
5
|
+
=== Someday ===
|
|
5
6
|
* Shorthand arguments to Sunspot#search
|
|
6
7
|
* Rudimentary fulltext prefixing support
|
|
7
|
-
* commitWithin (need solr-ruby support for this)
|
|
8
|
-
* Support Solr functions (e.g. dismax :bf)
|
|
9
8
|
|
|
10
9
|
=== Solr 1.5 ===
|
|
11
10
|
* Field Collapsing (SOLR-236)
|
|
12
11
|
* Support for official spatial support (SOLR-773)
|
|
12
|
+
* Support sorting by function
|
|
13
|
+
* Support string constants in functions
|
data/bin/sunspot-solr
CHANGED
|
@@ -30,6 +30,10 @@ OptionParser.new do |opts|
|
|
|
30
30
|
server.solr_home = File.expand_path(s)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
opts.on '-j', '--solr-jar=JAR', 'Solr start jar' do |j|
|
|
34
|
+
server.solr_jar = File.expand_path(j)
|
|
35
|
+
end
|
|
36
|
+
|
|
33
37
|
opts.on '--pid-dir=PID_DIR', 'Directory for pid files' do |pd|
|
|
34
38
|
server.pid_dir = File.expand_path(pd)
|
|
35
39
|
end
|
data/installer/config/schema.yml
CHANGED
|
@@ -12,37 +12,60 @@ types: !omap
|
|
|
12
12
|
- boolean:
|
|
13
13
|
class: BoolField
|
|
14
14
|
suffix: b
|
|
15
|
+
invariants:
|
|
16
|
+
termVectors: valse
|
|
15
17
|
- date:
|
|
16
18
|
class: DateField
|
|
17
19
|
suffix: d
|
|
20
|
+
invariants:
|
|
21
|
+
termVectors: valse
|
|
18
22
|
- rand:
|
|
19
23
|
class: RandomSortField
|
|
20
24
|
- sdouble:
|
|
21
25
|
class: SortableDoubleField
|
|
22
26
|
suffix: e
|
|
27
|
+
invariants:
|
|
28
|
+
termVectors: valse
|
|
23
29
|
- sfloat:
|
|
24
30
|
class: SortableFloatField
|
|
25
31
|
suffix: f
|
|
32
|
+
invariants:
|
|
33
|
+
termVectors: valse
|
|
26
34
|
- sint:
|
|
27
35
|
class: SortableIntField
|
|
28
36
|
suffix: i
|
|
37
|
+
invariants:
|
|
38
|
+
termVectors: valse
|
|
29
39
|
- slong:
|
|
30
40
|
class: SortableLongField
|
|
31
41
|
suffix: l
|
|
42
|
+
invariants:
|
|
43
|
+
termVectors: valse
|
|
32
44
|
- string:
|
|
33
45
|
class: StrField
|
|
34
46
|
suffix: s
|
|
47
|
+
invariants:
|
|
48
|
+
termVectors: valse
|
|
35
49
|
- tint:
|
|
36
50
|
class: TrieIntField
|
|
37
51
|
suffix: it
|
|
52
|
+
invariants:
|
|
53
|
+
termVectors: valse
|
|
38
54
|
- tfloat:
|
|
39
55
|
class: TrieFloatField
|
|
40
56
|
suffix: ft
|
|
57
|
+
invariants:
|
|
58
|
+
termVectors: valse
|
|
41
59
|
- tdouble:
|
|
42
60
|
class: TrieDoubleField
|
|
61
|
+
suffix: et
|
|
62
|
+
invariants:
|
|
63
|
+
termVectors: valse
|
|
43
64
|
- tdate:
|
|
44
65
|
class: TrieDateField
|
|
45
66
|
suffix: dt
|
|
67
|
+
invariants:
|
|
68
|
+
termVectors: valse
|
|
46
69
|
fixed: !omap
|
|
47
70
|
- id:
|
|
48
71
|
type: string
|
|
@@ -69,3 +92,4 @@ fixed: !omap
|
|
|
69
92
|
variants: !omap
|
|
70
93
|
- multiValued: m
|
|
71
94
|
- stored: s
|
|
95
|
+
- termVectors: v
|
|
@@ -112,6 +112,10 @@ module Sunspot
|
|
|
112
112
|
@text_fields ||= text_fields_hash.values.map { |set| set.to_a }.flatten
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
+
def all_more_like_this_fields
|
|
116
|
+
@more_like_this_fields ||= more_like_this_fields_hash.values.map { |set| set.to_a }.flatten
|
|
117
|
+
end
|
|
118
|
+
|
|
115
119
|
private
|
|
116
120
|
|
|
117
121
|
#
|
|
@@ -132,6 +136,16 @@ module Sunspot
|
|
|
132
136
|
end
|
|
133
137
|
end
|
|
134
138
|
|
|
139
|
+
def more_like_this_fields_hash
|
|
140
|
+
@more_like_this_fields_hash ||=
|
|
141
|
+
setups.inject({}) do |hash, setup|
|
|
142
|
+
setup.all_more_like_this_fields.each do |more_like_this_field|
|
|
143
|
+
(hash[more_like_this_field.name] ||= Set.new) << more_like_this_field
|
|
144
|
+
end
|
|
145
|
+
hash
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
135
149
|
#
|
|
136
150
|
# Return a hash of field names to field objects, containing all fields
|
|
137
151
|
# that are common to all of the classes enclosed. In order for fields
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Sunspot
|
|
2
|
+
module DSL #:nodoc:
|
|
3
|
+
module Adjustable #:nodoc
|
|
4
|
+
# <strong>Expert:</strong> Adjust or reset the parameters passed to Solr.
|
|
5
|
+
# The adjustment will take place just before sending the params to solr,
|
|
6
|
+
# after Sunspot builds the Solr params based on the methods called in the
|
|
7
|
+
# DSL.
|
|
8
|
+
#
|
|
9
|
+
# Under normal circumstances, using this method should not be necessary;
|
|
10
|
+
# if you find that it is, please consider submitting a feature request.
|
|
11
|
+
# Using this method requires knowledge of Sunspot's internal Solr schema
|
|
12
|
+
# and Solr query representations, which are not part of Sunspot's public
|
|
13
|
+
# API; they could change at any time. <strong>This method is unsupported
|
|
14
|
+
# and your mileage may vary.</strong>
|
|
15
|
+
#
|
|
16
|
+
# ==== Examples
|
|
17
|
+
#
|
|
18
|
+
# Sunspot.search(Post) do
|
|
19
|
+
# adjust_solr_params do |params|
|
|
20
|
+
# params[:q] += ' AND something_s:more'
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# Sunspot.more_like_this(my_post) do
|
|
25
|
+
# adjust_solr_params do |params|
|
|
26
|
+
# params["mlt.match.include"] = true
|
|
27
|
+
# end
|
|
28
|
+
# end
|
|
29
|
+
#
|
|
30
|
+
def adjust_solr_params( &block )
|
|
31
|
+
@query.solr_parameter_adjustment = block
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# <strong>Expert:</strong> Use a custom request handler for this search.
|
|
36
|
+
# The general use case for this would be a request handler configuration
|
|
37
|
+
# you've defined in solrconfig that has different search components,
|
|
38
|
+
# defaults, etc. Using this to point at an entirely different type of
|
|
39
|
+
# request handler that Sunspot doesn't support probably won't get you very
|
|
40
|
+
# far.
|
|
41
|
+
#
|
|
42
|
+
def request_handler(request_handler)
|
|
43
|
+
@search.request_handler = request_handler
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/sunspot/dsl/fulltext.rb
CHANGED
|
@@ -7,6 +7,9 @@ module Sunspot
|
|
|
7
7
|
class Fulltext
|
|
8
8
|
attr_reader :exclude_fields #:nodoc:
|
|
9
9
|
|
|
10
|
+
# accept function in boost
|
|
11
|
+
include Functional
|
|
12
|
+
|
|
10
13
|
def initialize(query, setup) #:nodoc:
|
|
11
14
|
@query, @setup = query, setup
|
|
12
15
|
@fields_added = false
|
|
@@ -139,10 +142,15 @@ module Sunspot
|
|
|
139
142
|
|
|
140
143
|
#
|
|
141
144
|
# Boost queries allow specification of an arbitrary scope for which
|
|
142
|
-
# matching documents should receive an extra boost.
|
|
145
|
+
# matching documents should receive an extra boost. You can either specify
|
|
146
|
+
# a boost factor and a block, or a boost function. The block is evaluated
|
|
143
147
|
# in the usual scope DSL, and field names are attribute fields, not text
|
|
144
148
|
# fields, as in other scope.
|
|
145
149
|
#
|
|
150
|
+
# The boost function can be a constant (numeric or string literal),
|
|
151
|
+
# a field name or another function. You can build arbitrarily complex
|
|
152
|
+
# functions, which are passed transparently to solr.
|
|
153
|
+
#
|
|
146
154
|
# This method can be called more than once for different boost queries
|
|
147
155
|
# with different boosts.
|
|
148
156
|
#
|
|
@@ -153,16 +161,23 @@ module Sunspot
|
|
|
153
161
|
# boost(2.0) do
|
|
154
162
|
# with(:featured, true)
|
|
155
163
|
# end
|
|
164
|
+
#
|
|
165
|
+
# boost(function { sum(:average_rating, product(:popularity, 10)) })
|
|
156
166
|
# end
|
|
157
167
|
# end
|
|
158
168
|
#
|
|
159
|
-
# In the above search, featured posts will receive a boost of 2.0
|
|
160
|
-
#
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
# In the above search, featured posts will receive a boost of 2.0 and all posts
|
|
170
|
+
# will be boosted by (average_rating + popularity * 10).
|
|
171
|
+
#
|
|
172
|
+
def boost(factor_or_function, &block)
|
|
173
|
+
if factor_or_function.is_a?(Sunspot::Query::FunctionQuery)
|
|
174
|
+
@query.add_boost_function(factor_or_function)
|
|
175
|
+
else
|
|
176
|
+
Sunspot::Util.instance_eval_or_call(
|
|
177
|
+
Scope.new(@query.create_boost_query(factor_or_function), @setup),
|
|
178
|
+
&block
|
|
179
|
+
)
|
|
180
|
+
end
|
|
166
181
|
end
|
|
167
182
|
|
|
168
183
|
#
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Sunspot
|
|
2
|
+
module DSL
|
|
3
|
+
class Function #:nodoc:
|
|
4
|
+
def initialize(functional) #:nodoc:
|
|
5
|
+
@functional = functional
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def method_missing(method, *args, &block)
|
|
9
|
+
function_args = args.map { |arg| @functional.create_function_query(arg) }
|
|
10
|
+
Sunspot::Query::FunctionalFunctionQuery.new(method, function_args)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Sunspot
|
|
2
|
+
module DSL
|
|
3
|
+
#
|
|
4
|
+
# Mixin DSL to accept functions.
|
|
5
|
+
#
|
|
6
|
+
module Functional
|
|
7
|
+
|
|
8
|
+
#
|
|
9
|
+
# Specify a function query with a block that returns an expression.
|
|
10
|
+
#
|
|
11
|
+
# === Examples
|
|
12
|
+
#
|
|
13
|
+
# function { 10 }
|
|
14
|
+
# function { :average_rating }
|
|
15
|
+
# function { sum(:average_rating, 10) }
|
|
16
|
+
#
|
|
17
|
+
def function(&block)
|
|
18
|
+
expression = Sunspot::Util.instance_eval_or_call(
|
|
19
|
+
Function.new(self),
|
|
20
|
+
&block
|
|
21
|
+
)
|
|
22
|
+
create_function_query(expression)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Creates an AbstractFunctionQuery from an expression, also called by
|
|
27
|
+
# Sunspot::DSL::Function
|
|
28
|
+
#
|
|
29
|
+
def create_function_query(expression) #:nodoc:
|
|
30
|
+
if expression.is_a?(Sunspot::Query::FunctionQuery)
|
|
31
|
+
expression
|
|
32
|
+
elsif expression.is_a?(Symbol)
|
|
33
|
+
Sunspot::Query::FieldFunctionQuery.new(@setup.field(expression))
|
|
34
|
+
else
|
|
35
|
+
Sunspot::Query::ConstantFunctionQuery.new(expression)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Sunspot
|
|
2
|
+
module DSL #:nodoc:
|
|
3
|
+
#
|
|
4
|
+
# This class provides the DSL for MoreLikeThis queries.
|
|
5
|
+
#
|
|
6
|
+
class MoreLikeThisQuery < FieldQuery
|
|
7
|
+
include Paginatable, Adjustable
|
|
8
|
+
|
|
9
|
+
def fields(*field_names)
|
|
10
|
+
boosted_fields = field_names.pop if field_names.last.is_a?(Hash)
|
|
11
|
+
field_names.each do |name|
|
|
12
|
+
mlt_fields = @setup.more_like_this_fields(name)
|
|
13
|
+
raise(ArgumentError, "Field #{name} is not setup for more_like_this") if mlt_fields.empty?
|
|
14
|
+
mlt_fields.each { |field| @query.more_like_this.add_field(field) }
|
|
15
|
+
end
|
|
16
|
+
if boosted_fields
|
|
17
|
+
boosted_fields.each_pair do |field_name, boost|
|
|
18
|
+
@setup.more_like_this_fields(field_name).each do |field|
|
|
19
|
+
@query.more_like_this.add_field(field, boost)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def minimum_term_frequency(value)
|
|
26
|
+
@query.more_like_this.minimum_term_frequency = value
|
|
27
|
+
end
|
|
28
|
+
alias_method :mintf, :minimum_term_frequency
|
|
29
|
+
|
|
30
|
+
def minimum_document_frequency(value)
|
|
31
|
+
@query.more_like_this.minimum_document_frequency = value
|
|
32
|
+
end
|
|
33
|
+
alias_method :mindf, :minimum_document_frequency
|
|
34
|
+
|
|
35
|
+
def minimum_word_length(value)
|
|
36
|
+
@query.more_like_this.minimum_word_length = value
|
|
37
|
+
end
|
|
38
|
+
alias_method :minwl, :minimum_word_length
|
|
39
|
+
|
|
40
|
+
def maximum_word_length(value)
|
|
41
|
+
@query.more_like_this.maximum_word_length = value
|
|
42
|
+
end
|
|
43
|
+
alias_method :maxwl, :maximum_word_length
|
|
44
|
+
|
|
45
|
+
def maximum_query_terms(value)
|
|
46
|
+
@query.more_like_this.maximum_query_terms = value
|
|
47
|
+
end
|
|
48
|
+
alias_method :maxqt, :maximum_query_terms
|
|
49
|
+
|
|
50
|
+
def boost_by_relevance(should_boost)
|
|
51
|
+
@query.more_like_this.boost_by_relevance = should_boost
|
|
52
|
+
end
|
|
53
|
+
alias_method :boost, :boost_by_relevance
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Sunspot
|
|
2
|
+
module DSL #:nodoc
|
|
3
|
+
module Paginatable
|
|
4
|
+
# Paginate your search. This works the same way as WillPaginate's
|
|
5
|
+
# paginate().
|
|
6
|
+
#
|
|
7
|
+
# Note that Solr searches are _always_ paginated. Not calling #paginate is
|
|
8
|
+
# the equivalent of calling:
|
|
9
|
+
#
|
|
10
|
+
# paginate(:page => 1, :per_page => Sunspot.config.pagination.default_per_page)
|
|
11
|
+
#
|
|
12
|
+
# ==== Options (options)
|
|
13
|
+
#
|
|
14
|
+
# :page<Integer,String>:: The requested page. The default is 1.
|
|
15
|
+
#
|
|
16
|
+
# :per_page<Integer,String>::
|
|
17
|
+
# How many results to return per page. The default is the value in
|
|
18
|
+
# +Sunspot.config.pagination.default_per_page+
|
|
19
|
+
#
|
|
20
|
+
def paginate(options = {})
|
|
21
|
+
page = options.delete(:page)
|
|
22
|
+
per_page = options.delete(:per_page)
|
|
23
|
+
raise ArgumentError, "unknown argument #{options.keys.first.inspect} passed to paginate" unless options.empty?
|
|
24
|
+
@query.paginate(page, per_page)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/sunspot/dsl/search.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Sunspot
|
|
|
5
5
|
# Sunspot.query. See Sunspot::DSL::Query, Sunspot::DSL::FieldQuery, and
|
|
6
6
|
# Sunspot::DSL::Scope for the full API presented.
|
|
7
7
|
#
|
|
8
|
-
class Search <
|
|
8
|
+
class Search < StandardQuery
|
|
9
9
|
def initialize(search, setup) #:nodoc:
|
|
10
10
|
@search = search
|
|
11
11
|
super(search, search.query, setup)
|
|
@@ -8,7 +8,9 @@ module Sunspot
|
|
|
8
8
|
#
|
|
9
9
|
# See Sunspot.search for usage examples
|
|
10
10
|
#
|
|
11
|
-
class
|
|
11
|
+
class StandardQuery < FieldQuery
|
|
12
|
+
include Paginatable, Adjustable
|
|
13
|
+
|
|
12
14
|
# Specify a phrase that should be searched as fulltext. Only +text+
|
|
13
15
|
# fields are searched - see DSL::Fields.text
|
|
14
16
|
#
|
|
@@ -53,7 +55,7 @@ module Sunspot
|
|
|
53
55
|
#
|
|
54
56
|
def fulltext(keywords, options = {}, &block)
|
|
55
57
|
if keywords && !(keywords.to_s =~ /^\s*$/)
|
|
56
|
-
fulltext_query = @query.
|
|
58
|
+
fulltext_query = @query.add_fulltext(keywords)
|
|
57
59
|
if field_names = options.delete(:fields)
|
|
58
60
|
Util.Array(field_names).each do |field_name|
|
|
59
61
|
@setup.text_fields(field_name).each do |field|
|
|
@@ -101,54 +103,7 @@ module Sunspot
|
|
|
101
103
|
end
|
|
102
104
|
alias_method :keywords, :fulltext
|
|
103
105
|
|
|
104
|
-
# Paginate your search. This works the same way as WillPaginate's
|
|
105
|
-
# paginate().
|
|
106
|
-
#
|
|
107
|
-
# Note that Solr searches are _always_ paginated. Not calling #paginate is
|
|
108
|
-
# the equivalent of calling:
|
|
109
|
-
#
|
|
110
|
-
# paginate(:page => 1, :per_page => Sunspot.config.pagination.default_per_page)
|
|
111
|
-
#
|
|
112
|
-
# ==== Options (options)
|
|
113
106
|
#
|
|
114
|
-
# :page<Integer,String>:: The requested page. The default is 1.
|
|
115
|
-
#
|
|
116
|
-
# :per_page<Integer,String>::
|
|
117
|
-
# How many results to return per page. The default is the value in
|
|
118
|
-
# +Sunspot.config.pagination.default_per_page+
|
|
119
|
-
#
|
|
120
|
-
def paginate(options = {})
|
|
121
|
-
page = options.delete(:page)
|
|
122
|
-
per_page = options.delete(:per_page)
|
|
123
|
-
raise ArgumentError, "unknown argument #{options.keys.first.inspect} passed to paginate" unless options.empty?
|
|
124
|
-
@query.paginate(page, per_page)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# <strong>Expert:</strong> Adjust or reset the parameters passed to Solr.
|
|
128
|
-
# The adjustment will take place just before sending the params to solr,
|
|
129
|
-
# after Sunspot builds the Solr params based on the methods called in the
|
|
130
|
-
# DSL.
|
|
131
|
-
#
|
|
132
|
-
# Under normal circumstances, using this method should not be necessary;
|
|
133
|
-
# if you find that it is, please consider submitting a feature request.
|
|
134
|
-
# Using this method requires knowledge of Sunspot's internal Solr schema
|
|
135
|
-
# and Solr query representations, which are not part of Sunspot's public
|
|
136
|
-
# API; they could change at any time. <strong>This method is unsupported
|
|
137
|
-
# and your mileage may vary.</strong>
|
|
138
|
-
#
|
|
139
|
-
# ==== Example
|
|
140
|
-
#
|
|
141
|
-
# Sunspot.search(Post) do
|
|
142
|
-
# adjust_solr_params do |params|
|
|
143
|
-
# params[:q] += ' AND something_s:more'
|
|
144
|
-
# end
|
|
145
|
-
# end
|
|
146
|
-
#
|
|
147
|
-
def adjust_solr_params( &block )
|
|
148
|
-
@query.set_solr_parameter_adjustment( block )
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
#
|
|
152
107
|
# Scope the search by geographical distance from a given point.
|
|
153
108
|
# +coordinates+ should either respond to #first and #last (e.g. a
|
|
154
109
|
# two-element array), or to #lat and one of #lng, #lon, or #long.
|
data/lib/sunspot/dsl.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
%w(fields scope field_query
|
|
2
|
-
search
|
|
1
|
+
%w(fields scope paginatable adjustable field_query standard_query query_facet
|
|
2
|
+
functional fulltext restriction search more_like_this_query
|
|
3
|
+
function).each do |file|
|
|
3
4
|
require File.join(File.dirname(__FILE__), 'dsl', file)
|
|
4
5
|
end
|
data/lib/sunspot/field.rb
CHANGED
|
@@ -10,6 +10,8 @@ module Sunspot
|
|
|
10
10
|
def initialize(name, type, options = {}) #:nodoc
|
|
11
11
|
@name, @type = name.to_sym, type
|
|
12
12
|
@stored = !!options.delete(:stored)
|
|
13
|
+
@more_like_this = !!options.delete(:more_like_this)
|
|
14
|
+
raise ArgumentError, "Field of type #{type} cannot be used for more_like_this" unless type.accepts_more_like_this? or !@more_like_this
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
# Convert a value to its representation for Solr indexing. This delegates
|
|
@@ -77,6 +79,18 @@ module Sunspot
|
|
|
77
79
|
!!@multiple
|
|
78
80
|
end
|
|
79
81
|
|
|
82
|
+
#
|
|
83
|
+
# Whether this field can be used for more_like_this queries.
|
|
84
|
+
# If true, the field is configured to store termVectors.
|
|
85
|
+
#
|
|
86
|
+
# ==== Returns
|
|
87
|
+
#
|
|
88
|
+
# Boolean:: True if this field can be used for more_like_this queries.
|
|
89
|
+
#
|
|
90
|
+
def more_like_this?
|
|
91
|
+
!!@more_like_this
|
|
92
|
+
end
|
|
93
|
+
|
|
80
94
|
def hash
|
|
81
95
|
indexed_name.hash
|
|
82
96
|
end
|
|
@@ -107,7 +121,7 @@ module Sunspot
|
|
|
107
121
|
end
|
|
108
122
|
|
|
109
123
|
def indexed_name
|
|
110
|
-
"#{super}#{'s' if @stored}"
|
|
124
|
+
"#{super}#{'s' if @stored}#{'v' if more_like_this?}"
|
|
111
125
|
end
|
|
112
126
|
end
|
|
113
127
|
|
|
@@ -140,7 +154,7 @@ module Sunspot
|
|
|
140
154
|
# String:: The field's indexed name
|
|
141
155
|
#
|
|
142
156
|
def indexed_name
|
|
143
|
-
"#{super}#{'m' if @multiple}#{'s' if @stored}"
|
|
157
|
+
"#{super}#{'m' if @multiple}#{'s' if @stored}#{'v' if more_like_this?}"
|
|
144
158
|
end
|
|
145
159
|
end
|
|
146
160
|
|
data/lib/sunspot/indexer.rb
CHANGED
|
@@ -157,7 +157,7 @@ module Sunspot
|
|
|
157
157
|
|
|
158
158
|
def add_comment(node)
|
|
159
159
|
comment_message = " *** This #{node.name} is used by Sunspot! *** "
|
|
160
|
-
unless (comment = previous_non_text_sibling(node)) && comment.
|
|
160
|
+
unless (comment = previous_non_text_sibling(node)) && comment.comment? && comment.content =~ /Sunspot/
|
|
161
161
|
node.add_previous_sibling(Nokogiri::XML::Comment.new(@document, comment_message))
|
|
162
162
|
end
|
|
163
163
|
end
|
|
@@ -46,6 +46,7 @@ module Sunspot
|
|
|
46
46
|
@root = @document.root
|
|
47
47
|
maybe_create_spatial_component
|
|
48
48
|
maybe_add_spatial_component_to_standard_handler
|
|
49
|
+
maybe_add_more_like_this_handler
|
|
49
50
|
original_path = "#{@solrconfig_path}.orig"
|
|
50
51
|
FileUtils.cp(@solrconfig_path, original_path)
|
|
51
52
|
say("Saved backup of original to #{original_path}")
|
|
@@ -88,6 +89,18 @@ module Sunspot
|
|
|
88
89
|
add_element(last_components_node, 'str').content = 'spatial'
|
|
89
90
|
end
|
|
90
91
|
end
|
|
92
|
+
|
|
93
|
+
def maybe_add_more_like_this_handler
|
|
94
|
+
unless @root.xpath('requestHandler[@name="/mlt"]').first
|
|
95
|
+
mlt_node = add_element(
|
|
96
|
+
@root, 'requestHandler',
|
|
97
|
+
:name => '/mlt', :class => 'solr.MoreLikeThisHandler'
|
|
98
|
+
)
|
|
99
|
+
defaults_node = add_element(mlt_node, 'lst', :name => 'defaults')
|
|
100
|
+
add_element(defaults_node, 'str', :name => 'mlt.mintf').content = '1'
|
|
101
|
+
add_element(defaults_node, 'str', :name => 'mlt.mindf').content = '2'
|
|
102
|
+
end
|
|
103
|
+
end
|
|
91
104
|
end
|
|
92
105
|
end
|
|
93
106
|
end
|
|
@@ -9,7 +9,7 @@ module Sunspot
|
|
|
9
9
|
|
|
10
10
|
def add_element(node, name, attributes = {})
|
|
11
11
|
new_node = Nokogiri::XML::Node.new(name, @document)
|
|
12
|
-
attributes.each_pair { |name, value| new_node[name] = value }
|
|
12
|
+
attributes.each_pair { |name, value| new_node[name.to_s] = value }
|
|
13
13
|
node << new_node
|
|
14
14
|
new_node
|
|
15
15
|
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Sunspot
|
|
2
2
|
module Query
|
|
3
3
|
class AbstractFieldFacet
|
|
4
|
+
include RSolr::Char
|
|
5
|
+
|
|
4
6
|
def initialize(field, options)
|
|
5
7
|
@field, @options = field, options
|
|
6
8
|
end
|
|
@@ -24,6 +26,9 @@ module Sunspot
|
|
|
24
26
|
if @options[:limit]
|
|
25
27
|
params[qualified_param('limit')] = @options[:limit].to_i
|
|
26
28
|
end
|
|
29
|
+
if @options[:prefix]
|
|
30
|
+
params[qualified_param('prefix')] = escape(@options[:prefix].to_s)
|
|
31
|
+
end
|
|
27
32
|
params[qualified_param('mincount')] =
|
|
28
33
|
case
|
|
29
34
|
when @options[:minimum_count] then @options[:minimum_count].to_i
|