sunspot 0.10.6 → 0.10.7
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/History.txt +7 -0
- data/README.rdoc +2 -1
- data/TODO +4 -0
- data/VERSION.yml +1 -1
- data/lib/sunspot.rb +1 -1
- data/lib/sunspot/adapters.rb +2 -2
- data/lib/sunspot/configuration.rb +0 -3
- data/lib/sunspot/dsl/field_query.rb +2 -2
- data/lib/sunspot/dsl/fields.rb +1 -1
- data/lib/sunspot/dsl/fulltext.rb +6 -2
- data/lib/sunspot/dsl/query.rb +2 -27
- data/lib/sunspot/dsl/scope.rb +26 -1
- data/lib/sunspot/field_factory.rb +2 -2
- data/lib/sunspot/indexer.rb +2 -2
- data/lib/sunspot/query/connective.rb +2 -2
- data/lib/sunspot/schema.rb +2 -2
- data/lib/sunspot/session.rb +4 -12
- data/lib/sunspot/util.rb +12 -0
- data/spec/api/indexer/attributes_spec.rb +5 -0
- data/spec/api/query/connectives_spec.rb +14 -0
- data/spec/api/query/fulltext_spec.rb +9 -0
- data/spec/api/session_spec.rb +0 -17
- data/spec/integration/indexing_spec.rb +7 -0
- data/spec/spec_helper.rb +8 -0
- data/tasks/gemspec.rake +2 -2
- metadata +9 -3
data/History.txt
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
== 0.10.7 2009-11-16
|
2
|
+
* Ignore boost_fields that don't apply
|
3
|
+
* Ability to specify text_fields inside connectives
|
4
|
+
* Fix bug with newlines in strings incorrectly being considered multi-value
|
5
|
+
* Compatibility with RSolr 0.10.1
|
6
|
+
* Remove commented-out code entirely
|
7
|
+
|
1
8
|
== 0.10.6 2009-11-05
|
2
9
|
* Support more dismax parameters
|
3
10
|
* Support multiple boost queries
|
data/README.rdoc
CHANGED
@@ -125,7 +125,7 @@ me so I can rectify the situation!
|
|
125
125
|
|
126
126
|
== Dependencies
|
127
127
|
|
128
|
-
1. RSolr 0.
|
128
|
+
1. RSolr 0.10.1
|
129
129
|
2. Daemons 1.x
|
130
130
|
4. Java 1.5+
|
131
131
|
|
@@ -184,6 +184,7 @@ Sunspot repository at `upstream`:
|
|
184
184
|
* Peter Berkenbosch (peterberkenbosch@me.com)
|
185
185
|
* Brian Atkinson
|
186
186
|
* Tom Coleman (tom@thesnail.org)
|
187
|
+
* Matt Mitchell (goodieboy@gmail.com)
|
187
188
|
|
188
189
|
== License
|
189
190
|
|
data/TODO
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
=== 0.10.x ===
|
2
|
+
* Can retrieve facets from search via string
|
3
|
+
* Allow #latitude and #longitude as coordinate attributes
|
4
|
+
* Allow use of #text_fields from inside disjunction
|
5
|
+
|
2
6
|
* Assumed inconsistency
|
3
7
|
* Support all operations in batches. Make it smart.
|
4
8
|
* Don't use more than one commits when one is equivalent
|
data/VERSION.yml
CHANGED
data/lib/sunspot.rb
CHANGED
@@ -161,7 +161,7 @@ module Sunspot
|
|
161
161
|
#
|
162
162
|
# ==== Example
|
163
163
|
#
|
164
|
-
# post1, post2 = Array(2) { Post.create }
|
164
|
+
# post1, post2 = new Array(2) { Post.create }
|
165
165
|
# Sunspot.index(post1, post2)
|
166
166
|
#
|
167
167
|
# Note that indexed objects won't be reflected in search until a commit is
|
data/lib/sunspot/adapters.rb
CHANGED
@@ -94,7 +94,7 @@ module Sunspot
|
|
94
94
|
# One or more classes that this instance adapter adapts
|
95
95
|
#
|
96
96
|
def register(instance_adapter, *classes)
|
97
|
-
|
97
|
+
classes.each do |clazz|
|
98
98
|
instance_adapters[clazz.name.to_sym] = instance_adapter
|
99
99
|
end
|
100
100
|
end
|
@@ -216,7 +216,7 @@ module Sunspot
|
|
216
216
|
# One or more classes that this data accessor providess access to
|
217
217
|
#
|
218
218
|
def register(data_accessor, *classes)
|
219
|
-
|
219
|
+
classes.each do |clazz|
|
220
220
|
data_accessors[clazz.name.to_sym] = data_accessor
|
221
221
|
end
|
222
222
|
end
|
@@ -84,7 +84,7 @@ module Sunspot
|
|
84
84
|
field_names.each do |field_name|
|
85
85
|
field = @setup.field(field_name)
|
86
86
|
search_facet = @search.add_field_facet(field, options)
|
87
|
-
Array(options[:only]).each do |value|
|
87
|
+
Util.Array(options[:only]).each do |value|
|
88
88
|
facet = Sunspot::Query::QueryFacet.new
|
89
89
|
facet.add_restriction(field, Sunspot::Query::Restriction::EqualTo, value)
|
90
90
|
@query.add_query_facet(facet)
|
@@ -110,7 +110,7 @@ module Sunspot
|
|
110
110
|
Sunspot::Query::FieldFacet.new(field, options)
|
111
111
|
end
|
112
112
|
@query.add_field_facet(facet)
|
113
|
-
Array(options[:extra]).each do |extra|
|
113
|
+
Util.Array(options[:extra]).each do |extra|
|
114
114
|
extra_facet = Sunspot::Query::QueryFacet.new
|
115
115
|
case extra
|
116
116
|
when :any
|
data/lib/sunspot/dsl/fields.rb
CHANGED
data/lib/sunspot/dsl/fulltext.rb
CHANGED
@@ -179,8 +179,12 @@ module Sunspot
|
|
179
179
|
#
|
180
180
|
def boost_fields(boosts)
|
181
181
|
boosts.each_pair do |field_name, boost|
|
182
|
-
|
183
|
-
@
|
182
|
+
begin
|
183
|
+
@setup.text_fields(field_name).each do |field|
|
184
|
+
@query.add_fulltext_field(field, boost)
|
185
|
+
end
|
186
|
+
rescue Sunspot::UnrecognizedFieldError
|
187
|
+
# We'll let this one slide.
|
184
188
|
end
|
185
189
|
end
|
186
190
|
end
|
data/lib/sunspot/dsl/query.rb
CHANGED
@@ -55,7 +55,7 @@ module Sunspot
|
|
55
55
|
if keywords && !(keywords.to_s =~ /^\s*$/)
|
56
56
|
fulltext_query = @query.set_fulltext(keywords)
|
57
57
|
if field_names = options.delete(:fields)
|
58
|
-
Array(field_names).each do |field_name|
|
58
|
+
Util.Array(field_names).each do |field_name|
|
59
59
|
@setup.text_fields(field_name).each do |field|
|
60
60
|
fulltext_query.add_fulltext_field(field, field.default_boost)
|
61
61
|
end
|
@@ -75,7 +75,7 @@ module Sunspot
|
|
75
75
|
fulltext_query.add_highlight
|
76
76
|
else
|
77
77
|
highlight_fields = []
|
78
|
-
Array(highlight_field_names).each do |field_name|
|
78
|
+
Util.Array(highlight_field_names).each do |field_name|
|
79
79
|
highlight_fields.concat(@setup.text_fields(field_name))
|
80
80
|
end
|
81
81
|
fulltext_query.add_highlight(highlight_fields)
|
@@ -157,31 +157,6 @@ module Sunspot
|
|
157
157
|
def near(coordinates, miles)
|
158
158
|
@query.add_location_restriction(coordinates, miles)
|
159
159
|
end
|
160
|
-
|
161
|
-
#
|
162
|
-
# Apply scope-type restrictions on fulltext fields. In certain situations,
|
163
|
-
# it may be desirable to place logical restrictions on text fields.
|
164
|
-
# Remember that text fields are tokenized; your mileage may very.
|
165
|
-
#
|
166
|
-
# The block works exactly like a normal scope, except that the field names
|
167
|
-
# refer to text fields instead of attribute fields.
|
168
|
-
#
|
169
|
-
# === Example
|
170
|
-
#
|
171
|
-
# Sunspot.search(Post) do
|
172
|
-
# text_fields do
|
173
|
-
# with :body, nil
|
174
|
-
# end
|
175
|
-
# end
|
176
|
-
#
|
177
|
-
# This will return all documents that do not have a body.
|
178
|
-
#
|
179
|
-
def text_fields(&block)
|
180
|
-
Sunspot::Util.instance_eval_or_call(
|
181
|
-
Scope.new(@scope, TextFieldSetup.new(@setup)),
|
182
|
-
&block
|
183
|
-
)
|
184
|
-
end
|
185
160
|
end
|
186
161
|
end
|
187
162
|
end
|
data/lib/sunspot/dsl/scope.rb
CHANGED
@@ -117,7 +117,7 @@ module Sunspot
|
|
117
117
|
end
|
118
118
|
else
|
119
119
|
instances = args
|
120
|
-
|
120
|
+
instances.flatten.each do |instance|
|
121
121
|
@scope.add_negated_restriction(
|
122
122
|
IdField.instance,
|
123
123
|
Sunspot::Query::Restriction::EqualTo,
|
@@ -195,6 +195,31 @@ module Sunspot
|
|
195
195
|
&block
|
196
196
|
)
|
197
197
|
end
|
198
|
+
|
199
|
+
#
|
200
|
+
# Apply scope-type restrictions on fulltext fields. In certain situations,
|
201
|
+
# it may be desirable to place logical restrictions on text fields.
|
202
|
+
# Remember that text fields are tokenized; your mileage may very.
|
203
|
+
#
|
204
|
+
# The block works exactly like a normal scope, except that the field names
|
205
|
+
# refer to text fields instead of attribute fields.
|
206
|
+
#
|
207
|
+
# === Example
|
208
|
+
#
|
209
|
+
# Sunspot.search(Post) do
|
210
|
+
# text_fields do
|
211
|
+
# with :body, nil
|
212
|
+
# end
|
213
|
+
# end
|
214
|
+
#
|
215
|
+
# This will return all documents that do not have a body.
|
216
|
+
#
|
217
|
+
def text_fields(&block)
|
218
|
+
Sunspot::Util.instance_eval_or_call(
|
219
|
+
Scope.new(@scope, TextFieldSetup.new(@setup)),
|
220
|
+
&block
|
221
|
+
)
|
222
|
+
end
|
198
223
|
end
|
199
224
|
end
|
200
225
|
end
|
@@ -56,7 +56,7 @@ module Sunspot
|
|
56
56
|
#
|
57
57
|
def populate_document(document, model) #:nodoc:
|
58
58
|
unless (value = @data_extractor.value_for(model)).nil?
|
59
|
-
|
59
|
+
Util.Array(@field.to_indexed(value)).each do |scalar_value|
|
60
60
|
document.add_field(
|
61
61
|
@field.indexed_name.to_sym,
|
62
62
|
scalar_value, @field.attributes
|
@@ -105,7 +105,7 @@ module Sunspot
|
|
105
105
|
if values = @data_extractor.value_for(model)
|
106
106
|
values.each_pair do |dynamic_name, value|
|
107
107
|
field_instance = build(dynamic_name)
|
108
|
-
|
108
|
+
Util.Array(field_instance.to_indexed(value)).each do |scalar_value|
|
109
109
|
document.add_field(
|
110
110
|
field_instance.indexed_name.to_sym,
|
111
111
|
scalar_value
|
data/lib/sunspot/indexer.rb
CHANGED
@@ -21,7 +21,7 @@ module Sunspot
|
|
21
21
|
# model<Object>:: the model to index
|
22
22
|
#
|
23
23
|
def add(model)
|
24
|
-
documents = Array(model).map { |m| prepare(m) }
|
24
|
+
documents = Util.Array(model).map { |m| prepare(m) }
|
25
25
|
if @batch.nil?
|
26
26
|
add_documents(documents)
|
27
27
|
else
|
@@ -75,7 +75,7 @@ module Sunspot
|
|
75
75
|
if boost = setup.document_boost_for(model)
|
76
76
|
document.attrs[:boost] = boost
|
77
77
|
end
|
78
|
-
|
78
|
+
setup.all_field_factories.each do |field_factory|
|
79
79
|
field_factory.populate_document(document, model)
|
80
80
|
end
|
81
81
|
document
|
@@ -105,7 +105,7 @@ module Sunspot
|
|
105
105
|
#
|
106
106
|
def negate
|
107
107
|
negated = self.class.new(!negated?)
|
108
|
-
|
108
|
+
@components.each do |component|
|
109
109
|
negated.add_component(component)
|
110
110
|
end
|
111
111
|
negated
|
@@ -157,7 +157,7 @@ module Sunspot
|
|
157
157
|
#
|
158
158
|
def denormalize
|
159
159
|
denormalized = self.class.inverse.new(!negated?)
|
160
|
-
|
160
|
+
@components.each do |component|
|
161
161
|
denormalized.add_component(component.negate)
|
162
162
|
end
|
163
163
|
denormalized
|
data/lib/sunspot/schema.rb
CHANGED
@@ -47,8 +47,8 @@ module Sunspot
|
|
47
47
|
#
|
48
48
|
def dynamic_fields
|
49
49
|
fields = []
|
50
|
-
|
51
|
-
|
50
|
+
variant_combinations.each do |field_variants|
|
51
|
+
FIELD_TYPES.each do |type|
|
52
52
|
fields << DynamicField.new(type, field_variants)
|
53
53
|
end
|
54
54
|
end
|
data/lib/sunspot/session.rb
CHANGED
@@ -94,7 +94,7 @@ module Sunspot
|
|
94
94
|
def remove(*objects)
|
95
95
|
objects.flatten!
|
96
96
|
@deletes += objects.length
|
97
|
-
|
97
|
+
objects.each do |object|
|
98
98
|
indexer.remove(object)
|
99
99
|
end
|
100
100
|
end
|
@@ -138,9 +138,7 @@ module Sunspot
|
|
138
138
|
Indexer.remove_all(master_connection)
|
139
139
|
else
|
140
140
|
@deletes += classes.length
|
141
|
-
|
142
|
-
indexer.remove_all(clazz)
|
143
|
-
end
|
141
|
+
classes.each { |clazz| indexer.remove_all(clazz) }
|
144
142
|
end
|
145
143
|
end
|
146
144
|
|
@@ -203,13 +201,8 @@ module Sunspot
|
|
203
201
|
@connection ||=
|
204
202
|
begin
|
205
203
|
connection = self.class.connection_class.connect(
|
206
|
-
:url => config.solr.url
|
207
|
-
:adapter => config.http_client
|
204
|
+
:url => config.solr.url
|
208
205
|
)
|
209
|
-
connection.message.adapter =
|
210
|
-
RSolr::Message::Adapter.const_get(
|
211
|
-
Util.camel_case(config.xml_builder.to_s)
|
212
|
-
).new
|
213
206
|
connection
|
214
207
|
end
|
215
208
|
end
|
@@ -227,9 +220,8 @@ module Sunspot
|
|
227
220
|
begin
|
228
221
|
if config.master_solr.url && config.master_solr.url != config.solr.url
|
229
222
|
master_connection = self.class.connection_class.new(
|
230
|
-
RSolr::
|
223
|
+
RSolr::Connection::NetHttp.new(:url => config.master_solr.url)
|
231
224
|
)
|
232
|
-
master_connection.adapter.connector.adapter_name = config.http_client
|
233
225
|
master_connection
|
234
226
|
else
|
235
227
|
connection
|
data/lib/sunspot/util.rb
CHANGED
@@ -95,6 +95,18 @@ module Sunspot
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
+
#
|
99
|
+
# Ruby's treatment of Strings as Enumerables is heavily annoying. As far
|
100
|
+
# as I know the behavior of Kernel.Array() is otherwise fine.
|
101
|
+
#
|
102
|
+
def Array(object)
|
103
|
+
if object.is_a?(String)
|
104
|
+
[object]
|
105
|
+
else
|
106
|
+
super
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
98
110
|
#
|
99
111
|
# Perform a deep merge of hashes, returning the result as a new hash.
|
100
112
|
# See #deep_merge_into for rules used to merge the hashes
|
@@ -21,6 +21,11 @@ describe 'indexing attribute fields', :type => :indexer do
|
|
21
21
|
connection.should have_add_with(:category_ids_im => ['3', '14'])
|
22
22
|
end
|
23
23
|
|
24
|
+
it 'should not index a single-value field with newlines as multiple' do
|
25
|
+
session.index(post(:title => "Multi\nLine"))
|
26
|
+
connection.adds.last.first.field_by_name(:title_ss).value.should == "Multi\nLine"
|
27
|
+
end
|
28
|
+
|
24
29
|
it 'should correctly index a time field' do
|
25
30
|
session.index(
|
26
31
|
post(:published_at => Time.parse('1983-07-08 05:00:00 -0400'))
|
@@ -153,6 +153,20 @@ describe 'connective in scope', :type => :query do
|
|
153
153
|
)
|
154
154
|
end
|
155
155
|
|
156
|
+
it 'creates a disjunction with some text field components' do
|
157
|
+
session.search Post do
|
158
|
+
any_of do
|
159
|
+
text_fields do
|
160
|
+
with(:title).starting_with('test')
|
161
|
+
end
|
162
|
+
with(:blog_id, 1)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
connection.should have_last_search_including(
|
166
|
+
:fq, '(title_text:test* OR blog_id_i:1)'
|
167
|
+
)
|
168
|
+
end
|
169
|
+
|
156
170
|
it 'should ignore empty connectives' do
|
157
171
|
session.search Post do
|
158
172
|
any_of {}
|
@@ -151,6 +151,15 @@ describe 'fulltext query', :type => :query do
|
|
151
151
|
connection.searches.last[:qf].split(' ').sort.should == %w(backwards_title_text body_texts title_text^1.5)
|
152
152
|
end
|
153
153
|
|
154
|
+
it 'ignores boost fields that do not apply' do
|
155
|
+
session.search Post do
|
156
|
+
keywords 'great pizza' do
|
157
|
+
boost_fields :bogus => 1.2, :title => 1.5
|
158
|
+
end
|
159
|
+
end
|
160
|
+
connection.searches.last[:qf].split(' ').sort.should == %w(backwards_title_text body_texts title_text^1.5)
|
161
|
+
end
|
162
|
+
|
154
163
|
it 'sets default boost with default fields' do
|
155
164
|
session.search Photo do
|
156
165
|
keywords 'great pizza'
|
data/spec/api/session_spec.rb
CHANGED
@@ -75,23 +75,6 @@ describe 'Session' do
|
|
75
75
|
Sunspot.commit
|
76
76
|
connection.opts[:url].should == 'http://127.0.0.1:8981/solr'
|
77
77
|
end
|
78
|
-
|
79
|
-
it 'should use Net::HTTP adapter by default' do
|
80
|
-
Sunspot.commit
|
81
|
-
connection.adapter.should == :net_http
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'should use Net::HTTP adapter when specified' do
|
85
|
-
Sunspot.config.http_client = :curb
|
86
|
-
Sunspot.commit
|
87
|
-
connection.adapter.should == :curb
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'should use LibXML builder when specified' do
|
91
|
-
Sunspot.config.xml_builder = :libxml
|
92
|
-
Sunspot.commit
|
93
|
-
connection.message.adapter.should be_a(RSolr::Message::Adapter::Libxml)
|
94
|
-
end
|
95
78
|
end
|
96
79
|
|
97
80
|
context 'custom session' do
|
data/spec/spec_helper.rb
CHANGED
data/tasks/gemspec.rake
CHANGED
@@ -11,10 +11,10 @@ begin
|
|
11
11
|
s.description = <<TEXT
|
12
12
|
Sunspot is a library providing a powerful, all-ruby API for the Solr search engine. Sunspot manages the configuration of persistent Ruby classes for search and indexing and exposes Solr's most powerful features through a collection of DSLs. Complex search operations can be performed without hand-writing any boolean queries or building Solr parameters by hand.
|
13
13
|
TEXT
|
14
|
-
s.authors = ['Mat Brown', 'Peer Allan', 'Dmitriy Dzema', 'Benjamin Krause', 'Marcel de Graaf', 'Brandon Keepers', 'Peter Berkenbosch', 'Brian Atkinson', 'Tom Coleman']
|
14
|
+
s.authors = ['Mat Brown', 'Peer Allan', 'Dmitriy Dzema', 'Benjamin Krause', 'Marcel de Graaf', 'Brandon Keepers', 'Peter Berkenbosch', 'Brian Atkinson', 'Tom Coleman', 'Matt Mitchell']
|
15
15
|
s.rubyforge_project = 'sunspot'
|
16
16
|
s.files = FileList['[A-Z]*', '{bin,lib,spec,tasks,templates}/**/*', 'solr/{etc,lib,webapps}/**/*', 'solr/solr/{conf,lib}/*', 'solr/start.jar']
|
17
|
-
s.add_dependency 'rsolr', '
|
17
|
+
s.add_dependency 'rsolr', '>= 0.9.6', '<= 0.10.1'
|
18
18
|
s.add_dependency 'daemons', '~> 1.0'
|
19
19
|
s.add_development_dependency 'rspec', '~> 1.1'
|
20
20
|
s.add_development_dependency 'ruby-debug', '~> 0.10'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sunspot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Brown
|
@@ -13,11 +13,12 @@ authors:
|
|
13
13
|
- Peter Berkenbosch
|
14
14
|
- Brian Atkinson
|
15
15
|
- Tom Coleman
|
16
|
+
- Matt Mitchell
|
16
17
|
autorequire:
|
17
18
|
bindir: bin
|
18
19
|
cert_chain: []
|
19
20
|
|
20
|
-
date: 2009-11-
|
21
|
+
date: 2009-11-16 00:00:00 -05:00
|
21
22
|
default_executable:
|
22
23
|
dependencies:
|
23
24
|
- !ruby/object:Gem::Dependency
|
@@ -26,9 +27,12 @@ dependencies:
|
|
26
27
|
version_requirement:
|
27
28
|
version_requirements: !ruby/object:Gem::Requirement
|
28
29
|
requirements:
|
29
|
-
- - "
|
30
|
+
- - ">="
|
30
31
|
- !ruby/object:Gem::Version
|
31
32
|
version: 0.9.6
|
33
|
+
- - <=
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 0.10.1
|
32
36
|
version:
|
33
37
|
- !ruby/object:Gem::Dependency
|
34
38
|
name: daemons
|
@@ -198,6 +202,7 @@ files:
|
|
198
202
|
- spec/integration/dynamic_fields_spec.rb
|
199
203
|
- spec/integration/faceting_spec.rb
|
200
204
|
- spec/integration/highlighting_spec.rb
|
205
|
+
- spec/integration/indexing_spec.rb
|
201
206
|
- spec/integration/keyword_search_spec.rb
|
202
207
|
- spec/integration/local_search_spec.rb
|
203
208
|
- spec/integration/scoped_search_spec.rb
|
@@ -266,6 +271,7 @@ test_files:
|
|
266
271
|
- spec/integration/scoped_search_spec.rb
|
267
272
|
- spec/integration/highlighting_spec.rb
|
268
273
|
- spec/integration/keyword_search_spec.rb
|
274
|
+
- spec/integration/indexing_spec.rb
|
269
275
|
- spec/integration/dynamic_fields_spec.rb
|
270
276
|
- spec/integration/stored_fields_spec.rb
|
271
277
|
- spec/integration/test_pagination.rb
|