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/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
== 0.10.6 2009-11-05
|
2
|
+
* Support more dismax parameters
|
3
|
+
* Support multiple boost queries
|
4
|
+
* Allow "extra" facet rows
|
5
|
+
* Allow exclusion of fulltext fields
|
6
|
+
* Allow specification of per-field highlighting params
|
7
|
+
* Specify coordinates using block extraction
|
8
|
+
* Return empty array if no highlights available
|
9
|
+
* Get stored text fields from hits
|
10
|
+
* Update docs to reflect a requirement of at least one search type
|
11
|
+
* added --max-memory and --min-memory parameters to sunspot-solr
|
12
|
+
* LocalLucene and LocalSolr compatible with Java 1.5
|
13
|
+
|
1
14
|
== 0.10.5 2009-10-22
|
2
15
|
* Fix highlighting for multiple-model search
|
3
16
|
|
data/README.rdoc
CHANGED
@@ -125,9 +125,9 @@ me so I can rectify the situation!
|
|
125
125
|
|
126
126
|
== Dependencies
|
127
127
|
|
128
|
-
1. RSolr
|
129
|
-
2. Daemons
|
130
|
-
4. Java
|
128
|
+
1. RSolr 0.9.6
|
129
|
+
2. Daemons 1.x
|
130
|
+
4. Java 1.5+
|
131
131
|
|
132
132
|
Sunspot has been tested with MRI 1.8.6 and 1.8.7, REE 1.8.6, YARV 1.9.1, and
|
133
133
|
JRuby 1.2.0
|
data/TODO
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
=== 0.10 ===
|
2
|
-
*
|
3
|
-
* Allow boosting without field constraints
|
4
|
-
* Allow coordinates to be specified with block in setup
|
5
|
-
=== 0.11 ===
|
1
|
+
=== 0.10.x ===
|
2
|
+
* Assumed inconsistency
|
6
3
|
* Support all operations in batches. Make it smart.
|
7
4
|
* Don't use more than one commits when one is equivalent
|
8
5
|
* Preserve adds/deletes that are done after last commit
|
9
6
|
* Don't do adds and deletes for the same document out of order
|
10
7
|
* Don't do more than one add for the same document
|
11
8
|
* Do use as few requests as possible within those constraints
|
9
|
+
=== Future ===
|
10
|
+
* Support Solr functions (e.g. dismax :bf)
|
data/VERSION.yml
CHANGED
data/bin/sunspot-solr
CHANGED
@@ -19,12 +19,14 @@ end
|
|
19
19
|
working_directory = FileUtils.pwd
|
20
20
|
solr_install = File.expand_path(File.join(File.dirname(__FILE__), '..', 'solr'))
|
21
21
|
|
22
|
-
port
|
23
|
-
data_dir
|
24
|
-
solr_home
|
25
|
-
pid_dir
|
26
|
-
log_file
|
27
|
-
log_level
|
22
|
+
port = '8983'
|
23
|
+
data_dir = File.expand_path(File.join(Dir.tmpdir, 'solr_data'))
|
24
|
+
solr_home = File.join(solr_install, 'solr')
|
25
|
+
pid_dir = working_directory
|
26
|
+
log_file = nil
|
27
|
+
log_level = 'OFF'
|
28
|
+
min_memory = '128m'
|
29
|
+
max_memory = '512m'
|
28
30
|
|
29
31
|
OptionParser.new do |opts|
|
30
32
|
opts.banner = "Usage: sunspot-solr start [options]"
|
@@ -52,6 +54,14 @@ OptionParser.new do |opts|
|
|
52
54
|
opts.on '--log-file=LOG_FILE', 'Path to Solr log file' do |lf|
|
53
55
|
log_file = File.expand_path(lf)
|
54
56
|
end
|
57
|
+
|
58
|
+
opts.on '--max-memory=MEMORY', 'Specify the maximum size of the memory allocation pool' do |mm|
|
59
|
+
max_memory = mm
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on '--min-memory=MEMORY', 'Specify the initial size of the memory allocation pool' do |mm|
|
63
|
+
min_memory = mm
|
64
|
+
end
|
55
65
|
end.parse!
|
56
66
|
|
57
67
|
options = { :dir_mode => :normal, :dir => pid_dir }
|
@@ -72,6 +82,8 @@ end
|
|
72
82
|
Daemons.run_proc('sunspot-solr', options) do
|
73
83
|
FileUtils.cd(solr_install) do
|
74
84
|
args = ['java']
|
85
|
+
args << "-Xms#{min_memory}"
|
86
|
+
args << "-Xmx#{max_memory}"
|
75
87
|
args << "-Djetty.port=#{port}" if port
|
76
88
|
args << "-Dsolr.data.dir=#{data_dir}" if data_dir
|
77
89
|
args << "-Dsolr.solr.home=#{solr_home}" if solr_home
|
@@ -6,8 +6,8 @@ module Sunspot
|
|
6
6
|
# query DSL.
|
7
7
|
#
|
8
8
|
class FieldQuery < Scope
|
9
|
-
def initialize(query, setup)
|
10
|
-
@query = query
|
9
|
+
def initialize(search, query, setup) #:nodoc:
|
10
|
+
@search, @query = search, query
|
11
11
|
super(query.scope, setup)
|
12
12
|
end
|
13
13
|
|
@@ -58,39 +58,90 @@ module Sunspot
|
|
58
58
|
# :zeros<Boolean>::
|
59
59
|
# Return facet rows for which there are no matches (equivalent to
|
60
60
|
# :minimum_count => 0). Default is false.
|
61
|
+
# :extra<Symbol,Array>::
|
62
|
+
# One or more of :any and :none. :any returns a facet row with a count
|
63
|
+
# of all matching documents that have some value for this field. :none
|
64
|
+
# returns a facet row with a count of all matching documents that have
|
65
|
+
# no value for this field. The facet row(s) corresponding to the extras
|
66
|
+
# have a value of the symbol passed.
|
61
67
|
#
|
62
68
|
def facet(*field_names, &block)
|
69
|
+
options = Sunspot::Util.extract_options_from(field_names)
|
70
|
+
|
63
71
|
if block
|
64
|
-
options =
|
65
|
-
if field_names.last.is_a?(Hash)
|
66
|
-
field_names.pop
|
67
|
-
else
|
68
|
-
{}
|
69
|
-
end
|
70
72
|
if field_names.length != 1
|
71
73
|
raise(
|
72
74
|
ArgumentError,
|
73
75
|
"wrong number of arguments (#{field_names.length} for 1)"
|
74
76
|
)
|
75
77
|
end
|
76
|
-
|
77
|
-
|
78
|
+
search_facet = @search.add_query_facet(field_names.first, options)
|
79
|
+
Sunspot::Util.instance_eval_or_call(
|
80
|
+
QueryFacet.new(@query, @setup, search_facet),
|
81
|
+
&block
|
82
|
+
)
|
83
|
+
elsif options[:only]
|
84
|
+
field_names.each do |field_name|
|
85
|
+
field = @setup.field(field_name)
|
86
|
+
search_facet = @search.add_field_facet(field, options)
|
87
|
+
Array(options[:only]).each do |value|
|
88
|
+
facet = Sunspot::Query::QueryFacet.new
|
89
|
+
facet.add_restriction(field, Sunspot::Query::Restriction::EqualTo, value)
|
90
|
+
@query.add_query_facet(facet)
|
91
|
+
search_facet.add_row(value, facet.to_boolean_phrase)
|
92
|
+
end
|
93
|
+
end
|
78
94
|
else
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
95
|
+
field_names.each do |field_name|
|
96
|
+
search_facet = nil
|
97
|
+
field = @setup.field(field_name)
|
98
|
+
facet =
|
99
|
+
if options[:time_range]
|
100
|
+
unless field.type == Sunspot::Type::TimeType
|
101
|
+
raise(
|
102
|
+
ArgumentError,
|
103
|
+
':time_range can only be specified for Date or Time fields'
|
104
|
+
)
|
105
|
+
end
|
106
|
+
search_facet = @search.add_date_facet(field, options)
|
107
|
+
Sunspot::Query::DateFieldFacet.new(field, options)
|
108
|
+
else
|
109
|
+
search_facet = @search.add_field_facet(field)
|
110
|
+
Sunspot::Query::FieldFacet.new(field, options)
|
111
|
+
end
|
112
|
+
@query.add_field_facet(facet)
|
113
|
+
Array(options[:extra]).each do |extra|
|
114
|
+
extra_facet = Sunspot::Query::QueryFacet.new
|
115
|
+
case extra
|
116
|
+
when :any
|
117
|
+
extra_facet.add_negated_restriction(
|
118
|
+
field,
|
119
|
+
Sunspot::Query::Restriction::EqualTo,
|
120
|
+
nil
|
121
|
+
)
|
122
|
+
when :none
|
123
|
+
extra_facet.add_restriction(
|
124
|
+
field,
|
125
|
+
Sunspot::Query::Restriction::EqualTo,
|
126
|
+
nil
|
127
|
+
)
|
128
|
+
else
|
129
|
+
raise(
|
130
|
+
ArgumentError,
|
131
|
+
"Allowed values for :extra are :any and :none"
|
132
|
+
)
|
133
|
+
end
|
134
|
+
search_facet.add_row(extra, extra_facet.to_boolean_phrase)
|
135
|
+
@query.add_query_facet(extra_facet)
|
84
136
|
end
|
85
|
-
for field_name in field_names
|
86
|
-
@query.add_field_facet(@setup.field(field_name), options)
|
87
137
|
end
|
88
138
|
end
|
89
139
|
end
|
90
140
|
|
91
141
|
def dynamic(base_name, &block)
|
142
|
+
dynamic_field_factory = @setup.dynamic_field_factory(base_name)
|
92
143
|
Sunspot::Util.instance_eval_or_call(
|
93
|
-
FieldQuery.new(@query,
|
144
|
+
FieldQuery.new(@search, @query, dynamic_field_factory),
|
94
145
|
&block
|
95
146
|
)
|
96
147
|
end
|
data/lib/sunspot/dsl/fields.rb
CHANGED
@@ -44,12 +44,13 @@ module Sunspot
|
|
44
44
|
end
|
45
45
|
|
46
46
|
#
|
47
|
-
# Specify a method that returns the geographical coordinates
|
48
|
-
# with the document. The object returned must respond to #first
|
49
|
-
# (e.g., a two-element Array); or to #lat and one of #lng, #lon,
|
47
|
+
# Specify a method or block that returns the geographical coordinates
|
48
|
+
# associated with the document. The object returned must respond to #first
|
49
|
+
# and #last (e.g., a two-element Array); or to #lat and one of #lng, #lon,
|
50
|
+
# or #long
|
50
51
|
#
|
51
|
-
def coordinates(name)
|
52
|
-
@setup.set_coordinates_field(name)
|
52
|
+
def coordinates(name = nil, &block)
|
53
|
+
@setup.set_coordinates_field(name, &block)
|
53
54
|
end
|
54
55
|
|
55
56
|
#
|
data/lib/sunspot/dsl/fulltext.rb
CHANGED
@@ -5,9 +5,12 @@ module Sunspot
|
|
5
5
|
# handler.
|
6
6
|
#
|
7
7
|
class Fulltext
|
8
|
+
attr_reader :exclude_fields #:nodoc:
|
9
|
+
|
8
10
|
def initialize(query, setup) #:nodoc:
|
9
11
|
@query, @setup = query, setup
|
10
12
|
@fields_added = false
|
13
|
+
@exclude_fields = []
|
11
14
|
end
|
12
15
|
|
13
16
|
#
|
@@ -46,6 +49,14 @@ module Sunspot
|
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
52
|
+
#
|
53
|
+
# Exclude the given fields from the search. All fields that are configured
|
54
|
+
# for the types under search and not listed here will be searched.
|
55
|
+
#
|
56
|
+
def exclude_fields(*field_names)
|
57
|
+
@exclude_fields.concat(field_names)
|
58
|
+
end
|
59
|
+
|
49
60
|
#
|
50
61
|
# Enable keyword highlighting for this search. By default, the fields
|
51
62
|
# under search will be highlighted; you may also may pass one or more
|
@@ -86,7 +97,7 @@ module Sunspot
|
|
86
97
|
fields = []
|
87
98
|
args.each { |field_name| fields.concat(@setup.text_fields(field_name)) }
|
88
99
|
|
89
|
-
@query.
|
100
|
+
@query.add_highlight(fields, options)
|
90
101
|
end
|
91
102
|
|
92
103
|
#
|
@@ -115,12 +126,26 @@ module Sunspot
|
|
115
126
|
end
|
116
127
|
end
|
117
128
|
|
129
|
+
#
|
130
|
+
# The maximum number of words that can appear between search terms for a
|
131
|
+
# field to qualify for phrase field boost. See #query_phrase_slop for
|
132
|
+
# examples. Phrase slop is only meaningful if phrase fields are specified
|
133
|
+
# (see #phrase_fields), and it does not have an effect on which results
|
134
|
+
# are returned; only on what their respective boosts are.
|
135
|
+
#
|
136
|
+
def phrase_slop(slop)
|
137
|
+
@query.phrase_slop = slop
|
138
|
+
end
|
139
|
+
|
118
140
|
#
|
119
141
|
# Boost queries allow specification of an arbitrary scope for which
|
120
142
|
# matching documents should receive an extra boost. The block is evaluated
|
121
143
|
# in the usual scope DSL, and field names are attribute fields, not text
|
122
144
|
# fields, as in other scope.
|
123
145
|
#
|
146
|
+
# This method can be called more than once for different boost queries
|
147
|
+
# with different boosts.
|
148
|
+
#
|
124
149
|
# === Example
|
125
150
|
#
|
126
151
|
# Sunspot.search(Post) do
|
@@ -159,6 +184,37 @@ module Sunspot
|
|
159
184
|
end
|
160
185
|
end
|
161
186
|
end
|
187
|
+
|
188
|
+
#
|
189
|
+
# The minimum number of search terms that a result must match. By
|
190
|
+
# default, all search terms must match; if the number of search terms
|
191
|
+
# is less than this number, the default behavior applies.
|
192
|
+
#
|
193
|
+
def minimum_match(minimum_match)
|
194
|
+
@query.minimum_match = minimum_match
|
195
|
+
end
|
196
|
+
|
197
|
+
#
|
198
|
+
# The number of words that can appear between the words in a
|
199
|
+
# user-entered phrase (i.e., keywords in quotes) and still match. For
|
200
|
+
# instance, in a search for "\"great pizza\"" with a query phrase slop of
|
201
|
+
# 1, "great pizza" and "great big pizza" will match, but "great monster of
|
202
|
+
# a pizza" will not. Default behavior is a query phrase slop of zero.
|
203
|
+
#
|
204
|
+
def query_phrase_slop(slop)
|
205
|
+
@query.query_phrase_slop = slop
|
206
|
+
end
|
207
|
+
|
208
|
+
#
|
209
|
+
# A tiebreaker coefficient for scores derived from subqueries that are
|
210
|
+
# lower-scoring than the maximum score subquery. Typically a near-zero
|
211
|
+
# value is useful. See
|
212
|
+
# http://wiki.apache.org/solr/DisMaxRequestHandler#tie_.28Tie_breaker.29
|
213
|
+
# for more information.
|
214
|
+
#
|
215
|
+
def tie(tie)
|
216
|
+
@query.tie = tie
|
217
|
+
end
|
162
218
|
|
163
219
|
def fields_added? #:nodoc:
|
164
220
|
@fields_added
|
data/lib/sunspot/dsl/query.rb
CHANGED
@@ -34,6 +34,22 @@ module Sunspot
|
|
34
34
|
# If true, perform keyword highlighting on all searched fields. If an
|
35
35
|
# array of field names, perform highlighting on the specified fields.
|
36
36
|
# This can also be called from within the fulltext block.
|
37
|
+
# :minimum_match<Integer>::
|
38
|
+
# The minimum number of search terms that a result must match. By
|
39
|
+
# default, all search terms must match; if the number of search terms
|
40
|
+
# is less than this number, the default behavior applies.
|
41
|
+
# :tie<Float>::
|
42
|
+
# A tiebreaker coefficient for scores derived from subqueries that are
|
43
|
+
# lower-scoring than the maximum score subquery. Typically a near-zero
|
44
|
+
# value is useful. See
|
45
|
+
# http://wiki.apache.org/solr/DisMaxRequestHandler#tie_.28Tie_breaker.29
|
46
|
+
# for more information.
|
47
|
+
# :query_phrase_slop<Integer>::
|
48
|
+
# The number of words that can appear between the words in a
|
49
|
+
# user-entered phrase (i.e., keywords in quotes) and still match. For
|
50
|
+
# instance, in a search for "\"great pizza\"" with a phrase slop of 1,
|
51
|
+
# "great pizza" and "great big pizza" will match, but "great monster of
|
52
|
+
# a pizza" will not. Default behavior is a query phrase slop of zero.
|
37
53
|
#
|
38
54
|
def fulltext(keywords, options = {}, &block)
|
39
55
|
if keywords && !(keywords.to_s =~ /^\s*$/)
|
@@ -45,15 +61,24 @@ module Sunspot
|
|
45
61
|
end
|
46
62
|
end
|
47
63
|
end
|
64
|
+
if minimum_match = options.delete(:minimum_match)
|
65
|
+
fulltext_query.minimum_match = minimum_match.to_i
|
66
|
+
end
|
67
|
+
if tie = options.delete(:tie)
|
68
|
+
fulltext_query.tie = tie.to_f
|
69
|
+
end
|
70
|
+
if query_phrase_slop = options.delete(:query_phrase_slop)
|
71
|
+
fulltext_query.query_phrase_slop = query_phrase_slop.to_i
|
72
|
+
end
|
48
73
|
if highlight_field_names = options.delete(:highlight)
|
49
74
|
if highlight_field_names == true
|
50
|
-
fulltext_query.
|
75
|
+
fulltext_query.add_highlight
|
51
76
|
else
|
52
77
|
highlight_fields = []
|
53
78
|
Array(highlight_field_names).each do |field_name|
|
54
79
|
highlight_fields.concat(@setup.text_fields(field_name))
|
55
80
|
end
|
56
|
-
fulltext_query.
|
81
|
+
fulltext_query.add_highlight(highlight_fields)
|
57
82
|
end
|
58
83
|
end
|
59
84
|
if block && fulltext_query
|
@@ -66,7 +91,9 @@ module Sunspot
|
|
66
91
|
if !field_names && (!fulltext_dsl || !fulltext_dsl.fields_added?)
|
67
92
|
@setup.all_text_fields.each do |field|
|
68
93
|
unless fulltext_query.has_fulltext_field?(field)
|
69
|
-
|
94
|
+
unless fulltext_dsl && fulltext_dsl.exclude_fields.include?(field.name)
|
95
|
+
fulltext_query.add_fulltext_field(field, field.default_boost)
|
96
|
+
end
|
70
97
|
end
|
71
98
|
end
|
72
99
|
end
|
@@ -5,8 +5,8 @@ module Sunspot
|
|
5
5
|
# method.
|
6
6
|
#
|
7
7
|
class QueryFacet
|
8
|
-
def initialize(
|
9
|
-
@
|
8
|
+
def initialize(query, setup, facet) #:nodoc:
|
9
|
+
@query, @setup, @facet = query, setup, facet
|
10
10
|
end
|
11
11
|
|
12
12
|
#
|
@@ -24,7 +24,12 @@ module Sunspot
|
|
24
24
|
# An object used to identify this facet row in the results.
|
25
25
|
#
|
26
26
|
def row(label, &block)
|
27
|
-
|
27
|
+
query_facet = Sunspot::Query::QueryFacet.new
|
28
|
+
Sunspot::Util.instance_eval_or_call(
|
29
|
+
Scope.new(@query.add_query_facet(query_facet), @setup),
|
30
|
+
&block
|
31
|
+
)
|
32
|
+
@facet.add_row(label, query_facet.to_boolean_phrase)
|
28
33
|
end
|
29
34
|
end
|
30
35
|
end
|
data/lib/sunspot/dsl/search.rb
CHANGED
data/lib/sunspot/dsl.rb
CHANGED
@@ -123,10 +123,13 @@ module Sunspot
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
#XXX Right now this doubles as a Field and a FieldFactory - good idea?
|
127
126
|
class Coordinates
|
128
|
-
def initialize(name)
|
129
|
-
|
127
|
+
def initialize(name = nil, &block)
|
128
|
+
if block
|
129
|
+
@data_extractor = DataExtractor::BlockExtractor.new(&block)
|
130
|
+
else
|
131
|
+
@data_extractor = DataExtractor::AttributeExtractor.new(name)
|
132
|
+
end
|
130
133
|
end
|
131
134
|
|
132
135
|
def populate_document(document, model)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class AbstractFieldFacet
|
4
|
+
def initialize(field, options)
|
5
|
+
@field, @options = field, options
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_params
|
9
|
+
params = {
|
10
|
+
:facet => 'true',
|
11
|
+
}
|
12
|
+
case @options[:sort]
|
13
|
+
when :count
|
14
|
+
params[qualified_param('sort')] = 'true'
|
15
|
+
when :index
|
16
|
+
params[qualified_param('sort')] = 'false'
|
17
|
+
when nil
|
18
|
+
else
|
19
|
+
raise(
|
20
|
+
ArgumentError,
|
21
|
+
"#{@options[:sort].inspect} is not an allowed value for :sort. Allowed options are :count and :index"
|
22
|
+
)
|
23
|
+
end
|
24
|
+
if @options[:limit]
|
25
|
+
params[qualified_param('limit')] = @options[:limit].to_i
|
26
|
+
end
|
27
|
+
params[qualified_param('mincount')] =
|
28
|
+
case
|
29
|
+
when @options[:minimum_count] then @options[:minimum_count].to_i
|
30
|
+
when @options[:zeros] then 0
|
31
|
+
else 1
|
32
|
+
end
|
33
|
+
params
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def qualified_param(param)
|
39
|
+
:"f.#{@field.indexed_name}.facet.#{param}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class DateFieldFacet < AbstractFieldFacet
|
4
|
+
def to_params
|
5
|
+
params = super
|
6
|
+
params[:"facet.date"] = [@field.indexed_name]
|
7
|
+
params[qualified_param('date.start')] = @field.to_indexed(@options[:time_range].first)
|
8
|
+
params[qualified_param('date.end')] = @field.to_indexed(@options[:time_range].last)
|
9
|
+
params[qualified_param('date.gap')] = "+#{@options[:time_interval] || 86400}SECONDS"
|
10
|
+
params
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/sunspot/query/dismax.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
module Sunspot
|
2
2
|
module Query
|
3
3
|
class Dismax
|
4
|
+
attr_writer :minimum_match, :phrase_slop, :query_phrase_slop, :tie
|
5
|
+
|
4
6
|
def initialize(keywords)
|
5
7
|
@keywords = keywords
|
6
8
|
@fulltext_fields = {}
|
9
|
+
@boost_queries = []
|
10
|
+
@highlights = []
|
7
11
|
end
|
8
12
|
|
9
13
|
#
|
@@ -17,11 +21,25 @@ module Sunspot
|
|
17
21
|
if @phrase_fields
|
18
22
|
params[:pf] = @phrase_fields.map { |field| field.to_boosted_field }.join(' ')
|
19
23
|
end
|
20
|
-
|
21
|
-
params[:bq] = @boost_query
|
24
|
+
unless @boost_queries.empty?
|
25
|
+
params[:bq] = @boost_queries.map do |boost_query|
|
26
|
+
boost_query.to_boolean_phrase
|
27
|
+
end
|
28
|
+
end
|
29
|
+
if @minimum_match
|
30
|
+
params[:mm] = @minimum_match
|
31
|
+
end
|
32
|
+
if @phrase_slop
|
33
|
+
params[:ps] = @phrase_slop
|
34
|
+
end
|
35
|
+
if @query_phrase_slop
|
36
|
+
params[:qs] = @query_phrase_slop
|
37
|
+
end
|
38
|
+
if @tie
|
39
|
+
params[:tie] = @tie
|
22
40
|
end
|
23
|
-
|
24
|
-
Sunspot::Util.deep_merge!(params,
|
41
|
+
@highlights.each do |highlight|
|
42
|
+
Sunspot::Util.deep_merge!(params, highlight.to_params)
|
25
43
|
end
|
26
44
|
params
|
27
45
|
end
|
@@ -30,7 +48,8 @@ module Sunspot
|
|
30
48
|
# Assign a new boost query and return it.
|
31
49
|
#
|
32
50
|
def create_boost_query(factor)
|
33
|
-
@boost_query = BoostQuery.new(factor)
|
51
|
+
@boost_queries << boost_query = BoostQuery.new(factor)
|
52
|
+
boost_query
|
34
53
|
end
|
35
54
|
|
36
55
|
#
|
@@ -53,8 +72,8 @@ module Sunspot
|
|
53
72
|
# Highlighting object won't pass field names at all, which means
|
54
73
|
# the dismax's :qf parameter will be used by Solr.
|
55
74
|
#
|
56
|
-
def
|
57
|
-
@
|
75
|
+
def add_highlight(fields=[], options={})
|
76
|
+
@highlights << Highlighting.new(fields, options)
|
58
77
|
end
|
59
78
|
|
60
79
|
#
|