sunspot 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|