sunspot 1.0.1 → 1.0.2
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 +6 -0
- data/lib/sunspot/query/restriction.rb +7 -0
- data/lib/sunspot/query/sort.rb +0 -10
- data/lib/sunspot/search.rb +27 -14
- data/lib/sunspot/search/hit.rb +2 -2
- data/lib/sunspot/server.rb +2 -2
- data/lib/sunspot/util.rb +4 -4
- data/lib/sunspot/version.rb +1 -1
- data/solr/solr/lib/solr-spatial-light-0.0.4.jar +0 -0
- data/spec/api/query/ordering_pagination_spec.rb +8 -0
- data/spec/api/query/scope_spec.rb +7 -0
- data/spec/api/search/faceting_spec.rb +11 -0
- data/spec/api/search/hits_spec.rb +5 -1
- data/spec/integration/local_search_spec.rb +17 -0
- data/spec/integration/scoped_search_spec.rb +9 -0
- data/spec/mocks/connection.rb +1 -1
- data/tasks/rdoc.rake +1 -1
- metadata +4 -4
- data/solr/solr/lib/solr-spatial-light-0.0.3.jar +0 -0
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 1.0.2 2010-03-11
|
2
|
+
* Restore Hit#distance for result geo distance
|
3
|
+
* Remove :distance special sort
|
4
|
+
* Quote reserved keywords in boolean queries
|
5
|
+
* Add Search#facets accessor to retrieve all facets
|
6
|
+
|
1
7
|
== 1.0.1 2010-03-05
|
2
8
|
* Copy all needed config files when sunspot-installer run with force option
|
3
9
|
|
@@ -40,6 +40,8 @@ module Sunspot
|
|
40
40
|
include Filter
|
41
41
|
include RSolr::Char
|
42
42
|
|
43
|
+
RESERVED_WORDS = Set['AND', 'OR', 'NOT']
|
44
|
+
|
43
45
|
def initialize(field, value, negated = false)
|
44
46
|
@field, @value, @negated = field, value, negated
|
45
47
|
end
|
@@ -133,6 +135,11 @@ module Sunspot
|
|
133
135
|
#
|
134
136
|
def solr_value(value = @value)
|
135
137
|
solr_value = escape(@field.to_indexed(value))
|
138
|
+
if RESERVED_WORDS.include?(solr_value)
|
139
|
+
%Q("#{solr_value}")
|
140
|
+
else
|
141
|
+
solr_value
|
142
|
+
end
|
136
143
|
end
|
137
144
|
end
|
138
145
|
|
data/lib/sunspot/query/sort.rb
CHANGED
@@ -90,16 +90,6 @@ module Sunspot
|
|
90
90
|
"score #{direction_for_solr}"
|
91
91
|
end
|
92
92
|
end
|
93
|
-
|
94
|
-
#
|
95
|
-
# A DistanceSort sorts by distance from the origin coordinates of a
|
96
|
-
# geographical distance search.
|
97
|
-
#
|
98
|
-
class DistanceSort < Abstract
|
99
|
-
def to_param
|
100
|
-
"geo_distance #{direction_for_solr}"
|
101
|
-
end
|
102
|
-
end
|
103
93
|
end
|
104
94
|
end
|
105
95
|
end
|
data/lib/sunspot/search.rb
CHANGED
@@ -11,16 +11,18 @@ module Sunspot
|
|
11
11
|
# Sunspot.new_search methods.
|
12
12
|
#
|
13
13
|
class Search
|
14
|
-
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
14
|
+
attr_reader :query #:nodoc:
|
15
|
+
#
|
16
|
+
# Retrieve all facet objects defined for this search, in order they were
|
17
|
+
# defined. To retrieve an individual facet by name, use #facet()
|
18
|
+
#
|
19
|
+
attr_reader :facets
|
19
20
|
|
20
21
|
def initialize(connection, setup, query, configuration) #:nodoc:
|
21
22
|
@connection, @setup, @query = connection, setup, query
|
22
23
|
@query.paginate(1, configuration.pagination.default_per_page)
|
23
|
-
@facets =
|
24
|
+
@facets = []
|
25
|
+
@facets_by_name = {}
|
24
26
|
end
|
25
27
|
|
26
28
|
#
|
@@ -78,7 +80,7 @@ module Sunspot
|
|
78
80
|
@hits ||=
|
79
81
|
maybe_will_paginate(
|
80
82
|
solr_response['docs'].map do |doc|
|
81
|
-
Hit.new(doc, highlights_for(doc), self)
|
83
|
+
Hit.new(doc, highlights_for(doc), distance_for(doc), self)
|
82
84
|
end
|
83
85
|
)
|
84
86
|
end
|
@@ -153,9 +155,9 @@ module Sunspot
|
|
153
155
|
def facet(name, dynamic_name = nil)
|
154
156
|
if name
|
155
157
|
if dynamic_name
|
156
|
-
@
|
158
|
+
@facets_by_name[:"#{name}:#{dynamic_name}"]
|
157
159
|
else
|
158
|
-
@
|
160
|
+
@facets_by_name[name.to_sym]
|
159
161
|
end
|
160
162
|
end
|
161
163
|
end
|
@@ -223,17 +225,17 @@ module Sunspot
|
|
223
225
|
end
|
224
226
|
|
225
227
|
def add_field_facet(field, options = {}) #:nodoc:
|
226
|
-
name = (options[:name] || field.name)
|
227
|
-
|
228
|
+
name = (options[:name] || field.name)
|
229
|
+
add_facet(name, FieldFacet.new(field, self, options))
|
228
230
|
end
|
229
231
|
|
230
232
|
def add_date_facet(field, options) #:nodoc:
|
231
|
-
name = (options[:name] || field.name)
|
232
|
-
|
233
|
+
name = (options[:name] || field.name)
|
234
|
+
add_facet(name, DateFacet.new(field, self, options))
|
233
235
|
end
|
234
236
|
|
235
237
|
def add_query_facet(name, options) #:nodoc:
|
236
|
-
|
238
|
+
add_facet(name, QueryFacet.new(name, self, options))
|
237
239
|
end
|
238
240
|
|
239
241
|
def facet_response #:nodoc:
|
@@ -256,6 +258,12 @@ module Sunspot
|
|
256
258
|
end
|
257
259
|
end
|
258
260
|
|
261
|
+
def distance_for(doc)
|
262
|
+
if @solr_result['distances']
|
263
|
+
@solr_result['distances'][doc['id']]
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
259
267
|
def verified_hits
|
260
268
|
@verified_hits ||= maybe_will_paginate(hits.select { |hit| hit.instance })
|
261
269
|
end
|
@@ -274,5 +282,10 @@ module Sunspot
|
|
274
282
|
def reset
|
275
283
|
@results = @hits = @verified_hits = @total = @solr_response = @doc_ids = nil
|
276
284
|
end
|
285
|
+
|
286
|
+
def add_facet(name, facet)
|
287
|
+
@facets << facet
|
288
|
+
@facets_by_name[name.to_sym] = facet
|
289
|
+
end
|
277
290
|
end
|
278
291
|
end
|
data/lib/sunspot/search/hit.rb
CHANGED
@@ -30,10 +30,10 @@ module Sunspot
|
|
30
30
|
|
31
31
|
attr_writer :result #:nodoc:
|
32
32
|
|
33
|
-
def initialize(raw_hit, highlights, search) #:nodoc:
|
33
|
+
def initialize(raw_hit, highlights, distance, search) #:nodoc:
|
34
34
|
@class_name, @primary_key = *raw_hit['id'].match(/([^ ]+) (.+)/)[1..2]
|
35
35
|
@score = raw_hit['score']
|
36
|
-
@distance =
|
36
|
+
@distance = distance
|
37
37
|
@search = search
|
38
38
|
@stored_values = raw_hit
|
39
39
|
@stored_cache = {}
|
data/lib/sunspot/server.rb
CHANGED
@@ -2,8 +2,8 @@ require 'escape'
|
|
2
2
|
require 'set'
|
3
3
|
require 'tempfile'
|
4
4
|
|
5
|
-
module Sunspot
|
6
|
-
class Server
|
5
|
+
module Sunspot
|
6
|
+
class Server #:nodoc:
|
7
7
|
# Raised if #stop is called but the server is not running
|
8
8
|
ServerError = Class.new(RuntimeError)
|
9
9
|
AlreadyRunningError = Class.new(ServerError)
|
data/lib/sunspot/util.rb
CHANGED
@@ -187,8 +187,8 @@ module Sunspot
|
|
187
187
|
end
|
188
188
|
|
189
189
|
def lat
|
190
|
-
if @coords.respond_to?(:
|
191
|
-
@coords
|
190
|
+
if @coords.respond_to?(:first)
|
191
|
+
@coords.first
|
192
192
|
elsif @coords.respond_to?(:lat)
|
193
193
|
@coords.lat
|
194
194
|
else
|
@@ -197,8 +197,8 @@ module Sunspot
|
|
197
197
|
end
|
198
198
|
|
199
199
|
def lng
|
200
|
-
if @coords.respond_to?(:
|
201
|
-
@coords
|
200
|
+
if @coords.respond_to?(:last)
|
201
|
+
@coords.last
|
202
202
|
elsif @coords.respond_to?(:lng)
|
203
203
|
@coords.lng
|
204
204
|
elsif @coords.respond_to?(:lon)
|
data/lib/sunspot/version.rb
CHANGED
Binary file
|
@@ -71,6 +71,14 @@ describe 'ordering and pagination' do
|
|
71
71
|
end.should raise_error(ArgumentError)
|
72
72
|
end
|
73
73
|
|
74
|
+
it 'throws an UnrecognizedFieldError if :distance is given for sort' do
|
75
|
+
lambda do
|
76
|
+
session.search Post do
|
77
|
+
order_by :distance, :asc
|
78
|
+
end
|
79
|
+
end.should raise_error(Sunspot::UnrecognizedFieldError)
|
80
|
+
end
|
81
|
+
|
74
82
|
it 'does not allow ordering by multiple-value fields' do
|
75
83
|
lambda do
|
76
84
|
session.search Post do
|
@@ -15,6 +15,13 @@ describe 'scoped query', :type => :query do
|
|
15
15
|
connection.should have_last_search_including(:fq, 'title_ss:My\ Pet\ Post')
|
16
16
|
end
|
17
17
|
|
18
|
+
it 'scopes by exact match with a special string' do
|
19
|
+
session.search Post do
|
20
|
+
with :title, 'OR'
|
21
|
+
end
|
22
|
+
connection.should have_last_search_including(:fq, 'title_ss:"OR"')
|
23
|
+
end
|
24
|
+
|
18
25
|
it 'scopes by exact match with time' do
|
19
26
|
time = Time.parse('1983-07-08 05:00:00 -0400')
|
20
27
|
session.search Post do
|
@@ -17,6 +17,17 @@ describe 'faceting', :type => :search do
|
|
17
17
|
result.facet('title').field_name.should == :title
|
18
18
|
end
|
19
19
|
|
20
|
+
it 'returns all facets specified by search' do
|
21
|
+
stub_facet(:title_ss, { 'Author 1' => 1 })
|
22
|
+
stub_facet(:blog_id_i, { '1' => 3 })
|
23
|
+
result = session.search(Post) do
|
24
|
+
facet :title
|
25
|
+
facet :blog_id
|
26
|
+
end
|
27
|
+
result.facets.first.field_name.should == :title
|
28
|
+
result.facets.last.field_name.should == :blog_id
|
29
|
+
end
|
30
|
+
|
20
31
|
it 'returns string facet' do
|
21
32
|
stub_facet(:title_ss, 'Author 1' => 2, 'Author 2' => 1)
|
22
33
|
result = session.search Post do
|
@@ -123,7 +123,11 @@ describe 'hits', :type => :search do
|
|
123
123
|
end
|
124
124
|
|
125
125
|
it 'should return geo distance' do
|
126
|
-
|
126
|
+
post = Post.new
|
127
|
+
stub_results(post)
|
128
|
+
connection.response['distances'] = {
|
129
|
+
"Post #{post.id}" => 1.23
|
130
|
+
}
|
127
131
|
session.search(Post).hits.first.distance.should == 1.23
|
128
132
|
end
|
129
133
|
|
@@ -47,6 +47,14 @@ describe 'local search' do
|
|
47
47
|
end
|
48
48
|
search.results.should == [@posts[1]]
|
49
49
|
end
|
50
|
+
|
51
|
+
it 'should perform a radial search with attribute scoping and distance sorting' do
|
52
|
+
search = Sunspot.search(Post) do |query|
|
53
|
+
query.near(ORIGIN, :sort => true)
|
54
|
+
query.with(:title, 'teacup')
|
55
|
+
end
|
56
|
+
search.results.should == [@posts[1], @posts[4]]
|
57
|
+
end
|
50
58
|
|
51
59
|
it 'should order by arbitrary field' do
|
52
60
|
search = Sunspot.search(Post) do |query|
|
@@ -71,4 +79,13 @@ describe 'local search' do
|
|
71
79
|
end
|
72
80
|
end.should_not raise_error
|
73
81
|
end
|
82
|
+
|
83
|
+
it 'should return geographical distance from origin' do
|
84
|
+
search = Sunspot.search(Post) do |query|
|
85
|
+
query.near(ORIGIN, :sort => true)
|
86
|
+
end
|
87
|
+
search.hits.each do |hit|
|
88
|
+
hit.distance.should_not be_nil
|
89
|
+
end
|
90
|
+
end
|
74
91
|
end
|
@@ -119,6 +119,15 @@ describe 'scoped_search' do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
describe 'reserved words' do
|
123
|
+
%w(AND OR NOT TO).each do |word|
|
124
|
+
it "should successfully search for #{word.inspect}" do
|
125
|
+
Sunspot.index!(post = Post.new(:title => word))
|
126
|
+
Sunspot.search(Post) { with(:title, word) }.results.should == [post]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
122
131
|
describe 'passing nil value to equal' do
|
123
132
|
before :all do
|
124
133
|
Sunspot.remove_all
|
data/spec/mocks/connection.rb
CHANGED
data/tasks/rdoc.rake
CHANGED
@@ -20,7 +20,7 @@ namespace :doc do
|
|
20
20
|
desc 'Generate rdoc and move into pages directory'
|
21
21
|
task :publish => :redoc do
|
22
22
|
doc_dir = File.join(File.dirname(__FILE__), '..', 'doc')
|
23
|
-
publish_dir = File.join(File.dirname(__FILE__), '..', 'pages', 'docs')
|
23
|
+
publish_dir = File.join(File.dirname(__FILE__), '..', '..', 'pages', 'docs')
|
24
24
|
FileUtils.rm_rf(publish_dir) if File.exist?(publish_dir)
|
25
25
|
FileUtils.cp_r(doc_dir, publish_dir)
|
26
26
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
8
|
+
- 2
|
9
|
+
version: 1.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mat Brown
|
@@ -24,7 +24,7 @@ autorequire:
|
|
24
24
|
bindir: bin
|
25
25
|
cert_chain: []
|
26
26
|
|
27
|
-
date: 2010-03-
|
27
|
+
date: 2010-03-11 00:00:00 -05:00
|
28
28
|
default_executable:
|
29
29
|
dependencies:
|
30
30
|
- !ruby/object:Gem::Dependency
|
@@ -246,8 +246,8 @@ files:
|
|
246
246
|
- solr/solr/conf/scripts.conf
|
247
247
|
- solr/solr/conf/schema.xml
|
248
248
|
- solr/solr/conf/stopwords.txt
|
249
|
+
- solr/solr/lib/solr-spatial-light-0.0.4.jar
|
249
250
|
- solr/solr/lib/lucene-spatial-2.9.1.jar
|
250
|
-
- solr/solr/lib/solr-spatial-light-0.0.3.jar
|
251
251
|
- solr/start.jar
|
252
252
|
has_rdoc: true
|
253
253
|
homepage: http://outoftime.github.com/sunspot
|
Binary file
|