sunspot 2.2.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/sunspot/dsl/field_query.rb +11 -9
- data/lib/sunspot/dsl/fulltext.rb +9 -1
- data/lib/sunspot/dsl/group.rb +108 -0
- data/lib/sunspot/dsl/search.rb +1 -1
- data/lib/sunspot/dsl.rb +1 -1
- data/lib/sunspot/field_factory.rb +28 -15
- data/lib/sunspot/indexer.rb +63 -17
- data/lib/sunspot/query/abstract_fulltext.rb +9 -2
- data/lib/sunspot/query/dismax.rb +11 -4
- data/lib/sunspot/query/{field_group.rb → group.rb} +16 -6
- data/lib/sunspot/query/group_query.rb +17 -0
- data/lib/sunspot/query/restriction.rb +45 -1
- data/lib/sunspot/query.rb +1 -1
- data/lib/sunspot/schema.rb +2 -1
- data/lib/sunspot/search/abstract_search.rb +7 -3
- data/lib/sunspot/search/query_group.rb +74 -0
- data/lib/sunspot/search/standard_search.rb +1 -1
- data/lib/sunspot/search.rb +1 -1
- data/lib/sunspot/session.rb +16 -0
- data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +2 -2
- data/lib/sunspot/session_proxy/retry_5xx_session_proxy.rb +1 -1
- data/lib/sunspot/session_proxy/sharding_session_proxy.rb +4 -2
- data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +1 -1
- data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +3 -1
- data/lib/sunspot/type.rb +20 -0
- data/lib/sunspot/version.rb +1 -1
- data/lib/sunspot.rb +36 -2
- data/spec/api/indexer/attributes_spec.rb +5 -0
- data/spec/api/query/function_spec.rb +103 -0
- data/spec/api/query/group_spec.rb +23 -1
- data/spec/api/session_proxy/sharding_session_proxy_spec.rb +1 -1
- data/spec/helpers/integration_helper.rb +9 -0
- data/spec/integration/atomic_updates_spec.rb +44 -0
- data/spec/integration/field_grouping_spec.rb +13 -0
- data/spec/integration/scoped_search_spec.rb +51 -0
- data/spec/mocks/post.rb +3 -1
- metadata +11 -15
- data/lib/sunspot/dsl/field_group.rb +0 -57
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4a3b915b7cc088b4c26ba0eb4ae3e541666da526
|
4
|
+
data.tar.gz: a3021876e0d940137daf4527c0d3ac354f93119c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 62193e81b7834636ad0b2a03110e0054778700fe93a7cd6d6f5a52366708703bf3ce3a0ef24cf83d78a3d3532e79c274d893019aab1e26c289932e5b501bf005
|
7
|
+
data.tar.gz: 3a69aa3883a08bdab4c31ece01218cc3ac2a5bde250704448b9ca5e8dda070a1c7aaf401f7658621e2616f15596a84acc34319173dab91cb71a25b56a199db09
|
@@ -68,20 +68,22 @@ module Sunspot
|
|
68
68
|
#
|
69
69
|
# ==== Parameters
|
70
70
|
#
|
71
|
-
#
|
71
|
+
# field_names...<Symbol>:: the fields to use for grouping
|
72
72
|
def group(*field_names, &block)
|
73
|
+
group = Sunspot::Query::Group.new()
|
74
|
+
|
73
75
|
field_names.each do |field_name|
|
74
76
|
field = @setup.field(field_name)
|
75
|
-
group
|
76
|
-
|
77
|
+
group.add_field(field)
|
78
|
+
end
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
&block
|
82
|
-
)
|
83
|
-
end
|
80
|
+
if block
|
81
|
+
dsl = Group.new(@setup, group)
|
82
|
+
Sunspot::Util.instance_eval_or_call(dsl, &block)
|
84
83
|
end
|
84
|
+
|
85
|
+
@query.add_group(group)
|
86
|
+
@search.add_group(group)
|
85
87
|
end
|
86
88
|
|
87
89
|
#
|
data/lib/sunspot/dsl/fulltext.rb
CHANGED
@@ -168,8 +168,12 @@ module Sunspot
|
|
168
168
|
# will be boosted by (average_rating + popularity * 10).
|
169
169
|
#
|
170
170
|
def boost(factor_or_function, &block)
|
171
|
+
additive_boost(factor_or_function, &block)
|
172
|
+
end
|
173
|
+
|
174
|
+
def additive_boost(factor_or_function, &block)
|
171
175
|
if factor_or_function.is_a?(Sunspot::Query::FunctionQuery)
|
172
|
-
@query.
|
176
|
+
@query.add_additive_boost_function(factor_or_function)
|
173
177
|
else
|
174
178
|
Sunspot::Util.instance_eval_or_call(
|
175
179
|
Scope.new(@query.create_boost_query(factor_or_function), @setup),
|
@@ -178,6 +182,10 @@ module Sunspot
|
|
178
182
|
end
|
179
183
|
end
|
180
184
|
|
185
|
+
def multiplicative_boost(factor_or_function)
|
186
|
+
@query.add_multiplicative_boost_function(factor_or_function)
|
187
|
+
end
|
188
|
+
|
181
189
|
#
|
182
190
|
# Add boost to certain fields, without restricting which fields are
|
183
191
|
# searched.
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module DSL
|
3
|
+
class Group
|
4
|
+
def initialize(setup, group)
|
5
|
+
@setup, @group = setup, group
|
6
|
+
end
|
7
|
+
|
8
|
+
# Specify one or more fields for result grouping.
|
9
|
+
#
|
10
|
+
# ==== Parameters
|
11
|
+
#
|
12
|
+
# field_names...<Symbol>:: the fields to use for grouping
|
13
|
+
#
|
14
|
+
def field(*field_names, &block)
|
15
|
+
field_names.each do |field_name|
|
16
|
+
field = @setup.field(field_name)
|
17
|
+
@group.add_field(field)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Specify a query to group results by.
|
22
|
+
#
|
23
|
+
# ==== Parameters
|
24
|
+
#
|
25
|
+
# label<Object>:: a label for this group; when #value is called on this
|
26
|
+
# group's results, this label will be returned.
|
27
|
+
#
|
28
|
+
def query(label, &block)
|
29
|
+
group_query = Sunspot::Query::GroupQuery.new(label)
|
30
|
+
Sunspot::Util.instance_eval_or_call(Scope.new(group_query, @setup), &block)
|
31
|
+
@group.add_query(group_query)
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Sets the number of results (documents) to return for each group.
|
36
|
+
# Defaults to 1.
|
37
|
+
#
|
38
|
+
def limit(num)
|
39
|
+
@group.limit = num
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# If set, facet counts are based on the most relevant document of
|
44
|
+
# each group matching the query.
|
45
|
+
#
|
46
|
+
# Supported in Solr 3.4 and above.
|
47
|
+
#
|
48
|
+
# ==== Example
|
49
|
+
#
|
50
|
+
# Sunspot.search(Post) do
|
51
|
+
# group :title do
|
52
|
+
# truncate
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# facet :title, :extra => :any
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
def truncate
|
59
|
+
@group.truncate = true
|
60
|
+
end
|
61
|
+
|
62
|
+
# Specify the order that results should be returned in. This method can
|
63
|
+
# be called multiple times; precedence will be in the order given.
|
64
|
+
#
|
65
|
+
# ==== Parameters
|
66
|
+
#
|
67
|
+
# field_name<Symbol>:: the field to use for ordering
|
68
|
+
# direction<Symbol>:: :asc or :desc (default :asc)
|
69
|
+
#
|
70
|
+
def order_by(field_name, direction = nil)
|
71
|
+
sort =
|
72
|
+
if special = Sunspot::Query::Sort.special(field_name)
|
73
|
+
special.new(direction)
|
74
|
+
else
|
75
|
+
Sunspot::Query::Sort::FieldSort.new(
|
76
|
+
@setup.field(field_name), direction
|
77
|
+
)
|
78
|
+
end
|
79
|
+
@group.add_sort(sort)
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Specify that results should be ordered based on a
|
84
|
+
# FunctionQuery - http://wiki.apache.org/solr/FunctionQuery
|
85
|
+
# Solr 3.1 and up
|
86
|
+
#
|
87
|
+
# For example, to order by field1 + (field2*field3):
|
88
|
+
#
|
89
|
+
# order_by_function :sum, :field1, [:product, :field2, :field3], :desc
|
90
|
+
#
|
91
|
+
# ==== Parameters
|
92
|
+
# function_name<Symbol>::
|
93
|
+
# the function to run
|
94
|
+
# arguments::
|
95
|
+
# the arguments for this function.
|
96
|
+
# - Symbol for a field or function name
|
97
|
+
# - Array for a nested function
|
98
|
+
# - String for a literal constant
|
99
|
+
# direction<Symbol>::
|
100
|
+
# :asc or :desc
|
101
|
+
def order_by_function(*args)
|
102
|
+
@group.add_sort(
|
103
|
+
Sunspot::Query::Sort::FunctionSort.new(@setup,args)
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/sunspot/dsl/search.rb
CHANGED
data/lib/sunspot/dsl.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
%w(spellcheckable fields scope paginatable adjustable field_query
|
2
2
|
standard_query query_facet functional fulltext restriction
|
3
3
|
restriction_with_near search more_like_this_query function
|
4
|
-
|
4
|
+
group field_stats).each do |file|
|
5
5
|
require File.join(File.dirname(__FILE__), 'dsl', file)
|
6
6
|
end
|
@@ -22,6 +22,23 @@ module Sunspot
|
|
22
22
|
DataExtractor::AttributeExtractor.new(options.delete(:using) || name)
|
23
23
|
end
|
24
24
|
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Extract the encapsulated field's data from the given model and add it
|
28
|
+
# into the Solr document for indexing. (noop here for joins)
|
29
|
+
#
|
30
|
+
def populate_document(document, model, options = {}) #:nodoc:
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def extract_value(model, options = {})
|
36
|
+
if options.has_key?(:value)
|
37
|
+
options.delete(:value)
|
38
|
+
else
|
39
|
+
@data_extractor.value_for(model)
|
40
|
+
end
|
41
|
+
end
|
25
42
|
end
|
26
43
|
|
27
44
|
#
|
@@ -54,15 +71,16 @@ module Sunspot
|
|
54
71
|
# Extract the encapsulated field's data from the given model and add it
|
55
72
|
# into the Solr document for indexing.
|
56
73
|
#
|
57
|
-
def populate_document(document, model) #:nodoc:
|
58
|
-
|
74
|
+
def populate_document(document, model, options = {}) #:nodoc:
|
75
|
+
value = extract_value(model, options)
|
76
|
+
unless value.nil?
|
59
77
|
Util.Array(@field.to_indexed(value)).each do |scalar_value|
|
60
|
-
|
61
|
-
|
78
|
+
field_options = {}
|
79
|
+
field_options[:boost] = @field.boost if @field.boost
|
62
80
|
document.add_field(
|
63
81
|
@field.indexed_name.to_sym,
|
64
82
|
scalar_value,
|
65
|
-
options
|
83
|
+
field_options.merge(options)
|
66
84
|
)
|
67
85
|
end
|
68
86
|
end
|
@@ -92,14 +110,7 @@ module Sunspot
|
|
92
110
|
@field
|
93
111
|
end
|
94
112
|
|
95
|
-
#
|
96
|
-
# Extract the encapsulated field's data from the given model and add it
|
97
|
-
# into the Solr document for indexing. (noop here for joins)
|
98
113
|
#
|
99
|
-
def populate_document(document, model) #:nodoc:
|
100
|
-
end
|
101
|
-
|
102
|
-
#
|
103
114
|
# A unique signature identifying this field by name and type.
|
104
115
|
#
|
105
116
|
def signature
|
@@ -135,14 +146,16 @@ module Sunspot
|
|
135
146
|
# Generate dynamic fields based on hash returned by data accessor and
|
136
147
|
# add the field data to the document.
|
137
148
|
#
|
138
|
-
def populate_document(document, model)
|
139
|
-
|
149
|
+
def populate_document(document, model, options = {})
|
150
|
+
values = extract_value(model, options)
|
151
|
+
if values
|
140
152
|
values.each_pair do |dynamic_name, value|
|
141
153
|
field_instance = build(dynamic_name)
|
142
154
|
Util.Array(field_instance.to_indexed(value)).each do |scalar_value|
|
143
155
|
document.add_field(
|
144
156
|
field_instance.indexed_name.to_sym,
|
145
|
-
scalar_value
|
157
|
+
scalar_value,
|
158
|
+
options
|
146
159
|
)
|
147
160
|
end
|
148
161
|
end
|
data/lib/sunspot/indexer.rb
CHANGED
@@ -22,12 +22,23 @@ module Sunspot
|
|
22
22
|
# model<Object>:: the model to index
|
23
23
|
#
|
24
24
|
def add(model)
|
25
|
-
documents = Util.Array(model).map { |m|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
documents = Util.Array(model).map { |m| prepare_full_update(m) }
|
26
|
+
add_batch_documents(documents)
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Construct a representation of the given class instances for atomic properties update
|
31
|
+
# and send it to the connection for indexing
|
32
|
+
#
|
33
|
+
# ==== Parameters
|
34
|
+
#
|
35
|
+
# clazz<Class>:: the class of the models to be updated
|
36
|
+
# updates<Hash>:: hash of updates where keys are model ids
|
37
|
+
# and values are hash with property name/values to be updated
|
38
|
+
#
|
39
|
+
def add_atomic_update(clazz, updates={})
|
40
|
+
documents = updates.map { |id, m| prepare_atomic_update(clazz, id, m) }
|
41
|
+
add_batch_documents(documents)
|
31
42
|
end
|
32
43
|
|
33
44
|
#
|
@@ -49,7 +60,7 @@ module Sunspot
|
|
49
60
|
)
|
50
61
|
end
|
51
62
|
|
52
|
-
#
|
63
|
+
#
|
53
64
|
# Delete all documents of the class indexed by this indexer from Solr.
|
54
65
|
#
|
55
66
|
def remove_all(clazz = nil)
|
@@ -90,9 +101,9 @@ module Sunspot
|
|
90
101
|
#
|
91
102
|
# Convert documents into hash of indexed properties
|
92
103
|
#
|
93
|
-
def
|
94
|
-
document = document_for(model)
|
95
|
-
setup =
|
104
|
+
def prepare_full_update(model)
|
105
|
+
document = document_for(model.class, model.id)
|
106
|
+
setup = setup_for_object(model)
|
96
107
|
if boost = setup.document_boost_for(model)
|
97
108
|
document.attrs[:boost] = boost
|
98
109
|
end
|
@@ -102,20 +113,40 @@ module Sunspot
|
|
102
113
|
document
|
103
114
|
end
|
104
115
|
|
116
|
+
def prepare_atomic_update(clazz, id, updates = {})
|
117
|
+
document = document_for(clazz, id)
|
118
|
+
setup_for_class(clazz).all_field_factories.each do |field_factory|
|
119
|
+
if updates.has_key?(field_factory.name)
|
120
|
+
field_factory.populate_document(document, nil, value: updates[field_factory.name], update: :set)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
document
|
124
|
+
end
|
125
|
+
|
105
126
|
def add_documents(documents)
|
106
127
|
@connection.add(documents)
|
107
128
|
end
|
108
129
|
|
130
|
+
def add_batch_documents(documents)
|
131
|
+
if batcher.batching?
|
132
|
+
batcher.concat(documents)
|
133
|
+
else
|
134
|
+
add_documents(documents)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
109
138
|
#
|
110
139
|
# All indexed documents index and store the +id+ and +type+ fields.
|
111
140
|
# This method constructs the document hash containing those key-value
|
112
141
|
# pairs.
|
113
142
|
#
|
114
|
-
def document_for(
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
143
|
+
def document_for(clazz, id)
|
144
|
+
if Adapters::InstanceAdapter.for(clazz)
|
145
|
+
RSolr::Xml::Document.new(
|
146
|
+
id: Adapters::InstanceAdapter.index_id_for(clazz.name, id),
|
147
|
+
type: Util.superclasses_for(clazz).map(&:name)
|
148
|
+
)
|
149
|
+
end
|
119
150
|
end
|
120
151
|
|
121
152
|
#
|
@@ -129,8 +160,23 @@ module Sunspot
|
|
129
160
|
#
|
130
161
|
# Sunspot::Setup:: The setup for the object's class
|
131
162
|
#
|
132
|
-
def
|
133
|
-
|
163
|
+
def setup_for_object(object)
|
164
|
+
setup_for_class(object.class)
|
165
|
+
end
|
166
|
+
|
167
|
+
#
|
168
|
+
# Get the Setup object for the given class.
|
169
|
+
#
|
170
|
+
# ==== Parameters
|
171
|
+
#
|
172
|
+
# clazz<Class>:: The class whose setup is to be retrieved
|
173
|
+
#
|
174
|
+
# ==== Returns
|
175
|
+
#
|
176
|
+
# Sunspot::Setup:: The setup for the class
|
177
|
+
#
|
178
|
+
def setup_for_class(clazz)
|
179
|
+
Setup.for(clazz) || raise(NoSetupError, "Sunspot is not configured for #{clazz.inspect}")
|
134
180
|
end
|
135
181
|
end
|
136
182
|
end
|
@@ -18,8 +18,15 @@ module Sunspot
|
|
18
18
|
#
|
19
19
|
# Add a boost function
|
20
20
|
#
|
21
|
-
def
|
22
|
-
@
|
21
|
+
def add_additive_boost_function(function_query)
|
22
|
+
@additive_boost_functions << function_query
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Add a multiplicative boost function
|
27
|
+
#
|
28
|
+
def add_multiplicative_boost_function(function_query)
|
29
|
+
@multiplicative_boost_functions << function_query
|
23
30
|
end
|
24
31
|
|
25
32
|
#
|
data/lib/sunspot/query/dismax.rb
CHANGED
@@ -13,7 +13,8 @@ module Sunspot
|
|
13
13
|
@keywords = keywords
|
14
14
|
@fulltext_fields = {}
|
15
15
|
@boost_queries = []
|
16
|
-
@
|
16
|
+
@additive_boost_functions = []
|
17
|
+
@multiplicative_boost_functions = []
|
17
18
|
@highlights = []
|
18
19
|
|
19
20
|
@minimum_match = nil
|
@@ -46,9 +47,15 @@ module Sunspot
|
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
|
-
unless @
|
50
|
-
params[:bf] = @
|
51
|
-
|
50
|
+
unless @additive_boost_functions.empty?
|
51
|
+
params[:bf] = @additive_boost_functions.map do |additive_boost_function|
|
52
|
+
additive_boost_function.to_s
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
unless @multiplicative_boost_functions.empty?
|
57
|
+
params[:boost] = @multiplicative_boost_functions.map do |multiplicative_boost_function|
|
58
|
+
multiplicative_boost_function.to_s
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
@@ -1,18 +1,27 @@
|
|
1
1
|
module Sunspot
|
2
2
|
module Query
|
3
3
|
#
|
4
|
-
# A
|
4
|
+
# A Group groups by the unique values of a given field, or by given queries.
|
5
5
|
#
|
6
|
-
class
|
6
|
+
class Group
|
7
7
|
attr_accessor :limit, :truncate
|
8
|
+
attr_reader :fields, :queries
|
8
9
|
|
9
|
-
def initialize
|
10
|
+
def initialize
|
11
|
+
@sort = SortComposite.new
|
12
|
+
@fields = []
|
13
|
+
@queries = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_field(field)
|
10
17
|
if field.multiple?
|
11
18
|
raise(ArgumentError, "#{field.name} cannot be used for grouping because it is a multiple-value field")
|
12
19
|
end
|
13
|
-
@
|
20
|
+
@fields << field
|
21
|
+
end
|
14
22
|
|
15
|
-
|
23
|
+
def add_query(query)
|
24
|
+
@queries << query
|
16
25
|
end
|
17
26
|
|
18
27
|
def add_sort(sort)
|
@@ -23,10 +32,11 @@ module Sunspot
|
|
23
32
|
params = {
|
24
33
|
:group => "true",
|
25
34
|
:"group.ngroups" => "true",
|
26
|
-
:"group.field" => @field.indexed_name
|
27
35
|
}
|
28
36
|
|
29
37
|
params.merge!(@sort.to_params("group."))
|
38
|
+
params[:"group.field"] = @fields.map(&:indexed_name) if @fields.any?
|
39
|
+
params[:"group.query"] = @queries.map(&:to_boolean_phrase) if @queries.any?
|
30
40
|
params[:"group.limit"] = @limit if @limit
|
31
41
|
params[:"group.truncate"] = @truncate if @truncate
|
32
42
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
#
|
4
|
+
# Representation of a GroupQuery, which allows the searcher to specify a
|
5
|
+
# query to group matching documents. This is essentially a conjunction,
|
6
|
+
# with an extra instance variable containing the label for the group.
|
7
|
+
#
|
8
|
+
class GroupQuery < Connective::Conjunction #:nodoc:
|
9
|
+
attr_reader :label
|
10
|
+
|
11
|
+
def initialize(label, negated = false)
|
12
|
+
super(negated)
|
13
|
+
@label = label
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -11,7 +11,7 @@ module Sunspot
|
|
11
11
|
# Array:: Collection of restriction class names
|
12
12
|
#
|
13
13
|
def names
|
14
|
-
constants -
|
14
|
+
constants - abstract_constants
|
15
15
|
end
|
16
16
|
|
17
17
|
#
|
@@ -22,6 +22,17 @@ module Sunspot
|
|
22
22
|
@types ||= {}
|
23
23
|
@types[restriction_name.to_sym] ||= const_get(Sunspot::Util.camel_case(restriction_name.to_s))
|
24
24
|
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
#
|
29
|
+
# Return the names of all abstract restriction classes that should not
|
30
|
+
# be made available to the DSL. Considers abstract classes are any class
|
31
|
+
# ending with '::Base' or containing a namespace prefixed with 'Abstract'
|
32
|
+
#
|
33
|
+
def abstract_constants
|
34
|
+
constants.grep(/(^|::)(Base$|Abstract)/)
|
35
|
+
end
|
25
36
|
end
|
26
37
|
|
27
38
|
#
|
@@ -330,6 +341,39 @@ module Sunspot
|
|
330
341
|
"#{solr_value(@value)}*"
|
331
342
|
end
|
332
343
|
end
|
344
|
+
|
345
|
+
class AbstractRange < Between
|
346
|
+
private
|
347
|
+
|
348
|
+
def operation
|
349
|
+
@operation || self.class.name.split('::').last
|
350
|
+
end
|
351
|
+
|
352
|
+
def solr_value(value = @value)
|
353
|
+
@field.to_indexed(value)
|
354
|
+
end
|
355
|
+
|
356
|
+
def to_positive_boolean_phrase
|
357
|
+
"_query_:\"{!field f=#{@field.indexed_name} op=#{operation}}#{solr_value}\""
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
class Containing < AbstractRange
|
362
|
+
def initialize(negated, field, value)
|
363
|
+
@operation = 'Contains'
|
364
|
+
super
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
class Intersecting < AbstractRange
|
369
|
+
def initialize(negated, field, value)
|
370
|
+
@operation = 'Intersects'
|
371
|
+
super
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
class Within < AbstractRange
|
376
|
+
end
|
333
377
|
end
|
334
378
|
end
|
335
379
|
end
|
data/lib/sunspot/query.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
field_facet highlighting pagination restriction common_query spellcheck
|
3
3
|
standard_query more_like_this more_like_this_query geo geofilt bbox query_facet
|
4
4
|
scope sort sort_composite text_field_boost function_query field_stats
|
5
|
-
composite_fulltext
|
5
|
+
composite_fulltext group group_query).each do |file|
|
6
6
|
require(File.join(File.dirname(__FILE__), 'query', file))
|
7
7
|
end
|
8
8
|
module Sunspot
|
data/lib/sunspot/schema.rb
CHANGED
@@ -23,7 +23,8 @@ module Sunspot
|
|
23
23
|
FieldType.new('slong', 'SortableLong', 'l'),
|
24
24
|
FieldType.new('tint', 'TrieInteger', 'it'),
|
25
25
|
FieldType.new('tfloat', 'TrieFloat', 'ft'),
|
26
|
-
FieldType.new('tdate', 'TrieInt', 'dt')
|
26
|
+
FieldType.new('tdate', 'TrieInt', 'dt'),
|
27
|
+
FieldType.new('daterange', 'DateRange', 'dr')
|
27
28
|
|
28
29
|
]
|
29
30
|
|
@@ -222,8 +222,12 @@ module Sunspot
|
|
222
222
|
"<Sunspot::Search:#{query.to_params.inspect}>"
|
223
223
|
end
|
224
224
|
|
225
|
-
def
|
226
|
-
|
225
|
+
def add_group(group) #:nodoc:
|
226
|
+
group.fields.each do |field|
|
227
|
+
add_subgroup(field.name, FieldGroup.new(field, self))
|
228
|
+
end
|
229
|
+
|
230
|
+
add_subgroup(:queries, QueryGroup.new(group.queries, self)) if group.queries.any?
|
227
231
|
end
|
228
232
|
|
229
233
|
def add_field_facet(field, options = {}) #:nodoc:
|
@@ -303,7 +307,7 @@ module Sunspot
|
|
303
307
|
@stats_by_name[name.to_sym] = stats
|
304
308
|
end
|
305
309
|
|
306
|
-
def
|
310
|
+
def add_subgroup(name, group)
|
307
311
|
@groups << group
|
308
312
|
@groups_by_name[name.to_sym] = group
|
309
313
|
end
|