sunspot 0.10.5 → 0.10.6
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 +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
@@ -128,21 +128,118 @@ describe 'keyword search' do
|
|
128
128
|
Sunspot.index!(
|
129
129
|
@posts = [
|
130
130
|
Post.new(:title => 'Rhino', :featured => true),
|
131
|
-
Post.new(:title => 'Rhino', :
|
131
|
+
Post.new(:title => 'Rhino', :ratings_average => 3.3),
|
132
|
+
Post.new(:title => 'Rhino')
|
132
133
|
]
|
133
134
|
)
|
134
135
|
end
|
135
136
|
|
136
|
-
it 'should assign a higher
|
137
|
-
search = Sunspot.search(Post) do
|
138
|
-
keywords('rhino') do
|
137
|
+
it 'should assign a higher score to the document matching the boost query' do
|
138
|
+
search = Sunspot.search(Post) do |query|
|
139
|
+
query.keywords('rhino') do
|
139
140
|
boost(2.0) do
|
140
141
|
with(:featured, true)
|
141
142
|
end
|
142
143
|
end
|
144
|
+
query.without(@posts[1])
|
145
|
+
end
|
146
|
+
search.results.should == [@posts[0], @posts[2]]
|
147
|
+
search.hits[0].score.should > search.hits[1].score
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should assign scores in order of multiple boost query match' do
|
151
|
+
search = Sunspot.search(Post) do
|
152
|
+
keywords 'rhino' do
|
153
|
+
boost(2.0) { with(:featured, true) }
|
154
|
+
boost(1.5) { with(:average_rating).greater_than(3.0) }
|
155
|
+
end
|
143
156
|
end
|
144
157
|
search.results.should == @posts
|
145
158
|
search.hits[0].score.should > search.hits[1].score
|
159
|
+
search.hits[1].score.should > search.hits[2].score
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe 'minimum match' do
|
164
|
+
before do
|
165
|
+
Sunspot.remove_all
|
166
|
+
@posts = [
|
167
|
+
Post.new(:title => 'Pepperoni Sausage Anchovies'),
|
168
|
+
Post.new(:title => 'Pepperoni Tomatoes Mushrooms')
|
169
|
+
]
|
170
|
+
Sunspot.index!(@posts)
|
171
|
+
@search = Sunspot.search(Post) do
|
172
|
+
keywords 'pepperoni sausage extra cheese', :minimum_match => 2
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should match documents that contain the minimum_match number of search terms' do
|
177
|
+
@search.results.should include(@posts[0])
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should not match documents that do not contain the minimum_match number of search terms' do
|
181
|
+
@search.results.should_not include(@posts[1])
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe 'query phrase slop' do
|
186
|
+
before do
|
187
|
+
Sunspot.remove_all
|
188
|
+
@posts = [
|
189
|
+
Post.new(:title => 'One four'),
|
190
|
+
Post.new(:title => 'One three four'),
|
191
|
+
Post.new(:title => 'One two three four')
|
192
|
+
]
|
193
|
+
Sunspot.index!(@posts)
|
194
|
+
@search = Sunspot.search(Post) do
|
195
|
+
keywords '"one four"', :query_phrase_slop => 1
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'should match exact phrase' do
|
200
|
+
@search.results.should include(@posts[0])
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should match phrase divided by query phrase slop terms' do
|
204
|
+
@search.results.should include(@posts[1])
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should not match phrase divided by more than query phrase slop terms' do
|
208
|
+
@search.results.should_not include(@posts[2])
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe 'phrase field slop' do
|
213
|
+
before do
|
214
|
+
Sunspot.remove_all
|
215
|
+
@comments = [
|
216
|
+
Namespaced::Comment.new(:author_name => 'one four'),
|
217
|
+
Namespaced::Comment.new(:body => 'one four'),
|
218
|
+
Namespaced::Comment.new(:author_name => 'one three four'),
|
219
|
+
Namespaced::Comment.new(:body => 'one three four'),
|
220
|
+
Namespaced::Comment.new(:author_name => 'one two three four'),
|
221
|
+
Namespaced::Comment.new(:body => 'one two three four')
|
222
|
+
]
|
223
|
+
Sunspot.index!(@comments)
|
224
|
+
@search = Sunspot.search(Namespaced::Comment) do
|
225
|
+
keywords 'one four' do
|
226
|
+
phrase_fields :author_name => 3.0
|
227
|
+
phrase_slop 1
|
228
|
+
end
|
229
|
+
end
|
230
|
+
@sorted_hits = @search.hits.sort_by { |hit| @comments.index(hit.instance) }
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'should give phrase field boost to exact match' do
|
234
|
+
@sorted_hits[0].score.should > @sorted_hits[1].score
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'should give phrase field boost to match within slop' do
|
238
|
+
@sorted_hits[2].score.should > @sorted_hits[3].score
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'should not give phrase field boost to match beyond slop' do
|
242
|
+
@sorted_hits[4].score.should == @sorted_hits[5].score
|
146
243
|
end
|
147
244
|
end
|
148
245
|
end
|
data/spec/mocks/photo.rb
CHANGED
data/tasks/gemspec.rake
CHANGED
@@ -14,7 +14,7 @@ TEXT
|
|
14
14
|
s.authors = ['Mat Brown', 'Peer Allan', 'Dmitriy Dzema', 'Benjamin Krause', 'Marcel de Graaf', 'Brandon Keepers', 'Peter Berkenbosch', 'Brian Atkinson', 'Tom Coleman']
|
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 '
|
17
|
+
s.add_dependency 'rsolr', '= 0.9.6'
|
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'
|
@@ -31,6 +31,12 @@ TEXT
|
|
31
31
|
end
|
32
32
|
|
33
33
|
namespace :release do
|
34
|
+
task :tag do
|
35
|
+
version = Jeweler::VersionHelper.new(File.join(File.dirname(__FILE__), '..')).to_s
|
36
|
+
`git tag -a -m "Version #{version}" v#{version}`
|
37
|
+
`git push origin v#{version}:v#{version}`
|
38
|
+
end
|
39
|
+
|
34
40
|
desc "Release gem to RubyForge and GitHub"
|
35
|
-
task :all => [:
|
41
|
+
task :all => [:gemspec, :tag, :"rubyforge:release:gem", :"gemcutter:release"]
|
36
42
|
end
|
data/tasks/rcov.rake
CHANGED
@@ -12,7 +12,7 @@ end
|
|
12
12
|
namespace :rcov do
|
13
13
|
desc 'run api specs with rcov'
|
14
14
|
Spec::Rake::SpecTask.new('api') do |t|
|
15
|
-
t.spec_files = FileList['spec/api
|
15
|
+
t.spec_files = FileList['spec/api/**/*_spec.rb']
|
16
16
|
t.rcov = true
|
17
17
|
t.rcov_dir = File.join('coverage', 'api')
|
18
18
|
t.rcov_opts.concat(['--exclude', 'spec', '--sort', 'coverage', '--only-uncovered'])
|
@@ -20,7 +20,7 @@ namespace :rcov do
|
|
20
20
|
|
21
21
|
desc 'run integration specs with rcov'
|
22
22
|
Spec::Rake::SpecTask.new('integration') do |t|
|
23
|
-
t.spec_files = FileList['spec/integration
|
23
|
+
t.spec_files = FileList['spec/integration/**/*_spec.rb']
|
24
24
|
t.rcov = true
|
25
25
|
t.rcov_dir = File.join('coverage', 'integration')
|
26
26
|
t.rcov_opts.concat(['--exclude', 'spec', '--sort', 'coverage', '--only-uncovered'])
|
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.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Brown
|
@@ -17,11 +17,11 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2009-
|
20
|
+
date: 2009-11-05 00:00:00 -05:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
24
|
-
name:
|
24
|
+
name: rsolr
|
25
25
|
type: :runtime
|
26
26
|
version_requirement:
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -105,27 +105,21 @@ files:
|
|
105
105
|
- lib/sunspot/dsl/restriction.rb
|
106
106
|
- lib/sunspot/dsl/scope.rb
|
107
107
|
- lib/sunspot/dsl/search.rb
|
108
|
-
- lib/sunspot/facet.rb
|
109
|
-
- lib/sunspot/facet_data.rb
|
110
|
-
- lib/sunspot/facet_row.rb
|
111
108
|
- lib/sunspot/field.rb
|
112
109
|
- lib/sunspot/field_factory.rb
|
113
110
|
- lib/sunspot/indexer.rb
|
114
|
-
- lib/sunspot/instantiated_facet.rb
|
115
|
-
- lib/sunspot/instantiated_facet_row.rb
|
116
111
|
- lib/sunspot/query.rb
|
112
|
+
- lib/sunspot/query/abstract_field_facet.rb
|
117
113
|
- lib/sunspot/query/boost_query.rb
|
118
114
|
- lib/sunspot/query/connective.rb
|
115
|
+
- lib/sunspot/query/date_field_facet.rb
|
119
116
|
- lib/sunspot/query/dismax.rb
|
120
117
|
- lib/sunspot/query/field_facet.rb
|
121
|
-
- lib/sunspot/query/fulltext_base_query.rb
|
122
118
|
- lib/sunspot/query/highlighting.rb
|
123
119
|
- lib/sunspot/query/local.rb
|
124
120
|
- lib/sunspot/query/pagination.rb
|
125
121
|
- lib/sunspot/query/query.rb
|
126
122
|
- lib/sunspot/query/query_facet.rb
|
127
|
-
- lib/sunspot/query/query_facet_row.rb
|
128
|
-
- lib/sunspot/query/query_field_facet.rb
|
129
123
|
- lib/sunspot/query/restriction.rb
|
130
124
|
- lib/sunspot/query/scope.rb
|
131
125
|
- lib/sunspot/query/sort.rb
|
@@ -133,8 +127,12 @@ files:
|
|
133
127
|
- lib/sunspot/query/text_field_boost.rb
|
134
128
|
- lib/sunspot/schema.rb
|
135
129
|
- lib/sunspot/search.rb
|
130
|
+
- lib/sunspot/search/date_facet.rb
|
131
|
+
- lib/sunspot/search/facet_row.rb
|
132
|
+
- lib/sunspot/search/field_facet.rb
|
136
133
|
- lib/sunspot/search/highlight.rb
|
137
134
|
- lib/sunspot/search/hit.rb
|
135
|
+
- lib/sunspot/search/query_facet.rb
|
138
136
|
- lib/sunspot/session.rb
|
139
137
|
- lib/sunspot/setup.rb
|
140
138
|
- lib/sunspot/text_field_setup.rb
|
data/lib/sunspot/facet.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module Sunspot
|
2
|
-
class Facet
|
3
|
-
def initialize(facet_data) #:nodoc:
|
4
|
-
@facet_data = facet_data
|
5
|
-
end
|
6
|
-
|
7
|
-
#
|
8
|
-
# For field facets, this is the field name. For query facets, this is the
|
9
|
-
# name given to the #facet method in the DSL.
|
10
|
-
#
|
11
|
-
def name
|
12
|
-
@facet_data.name
|
13
|
-
end
|
14
|
-
alias_method :field_name, :name
|
15
|
-
|
16
|
-
#
|
17
|
-
# Collection of FacetRow objects containing the individual values returned
|
18
|
-
# by the facet.
|
19
|
-
#
|
20
|
-
def rows
|
21
|
-
@facet_data.rows { |value, count| FacetRow.new(value, count) }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/lib/sunspot/facet_data.rb
DELETED
@@ -1,169 +0,0 @@
|
|
1
|
-
require 'enumerator'
|
2
|
-
|
3
|
-
module Sunspot
|
4
|
-
#
|
5
|
-
# The FacetData classes encapsulate various sources of facet data (field
|
6
|
-
# facet, # date facet, query facet), presenting a polymorphic API to the Facet
|
7
|
-
# class.
|
8
|
-
#
|
9
|
-
module FacetData #:nodoc:all
|
10
|
-
#
|
11
|
-
# Base class for facet data.
|
12
|
-
#
|
13
|
-
class Abstract
|
14
|
-
attr_reader :field #:nodoc:
|
15
|
-
|
16
|
-
#
|
17
|
-
# The class that the field references, if any.
|
18
|
-
#
|
19
|
-
def reference
|
20
|
-
@field.reference if @field
|
21
|
-
end
|
22
|
-
|
23
|
-
#
|
24
|
-
# Cast the given value to the field's type, if it has one; otherwise just
|
25
|
-
# return the string.
|
26
|
-
#
|
27
|
-
def cast(value)
|
28
|
-
if @field
|
29
|
-
@field.cast(value)
|
30
|
-
else
|
31
|
-
value
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
#
|
36
|
-
# Given the raw facet row value, return what the Sunspot facet row object
|
37
|
-
# should present as the value. This can be overridden by subclasses.
|
38
|
-
#
|
39
|
-
def row_value(value)
|
40
|
-
cast(value)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
#
|
45
|
-
# FieldFacetData encapsulates the data returned by field facets
|
46
|
-
#
|
47
|
-
class FieldFacetData < Abstract
|
48
|
-
def initialize(facet_values, field)
|
49
|
-
@facet_values, @field = facet_values, field
|
50
|
-
end
|
51
|
-
|
52
|
-
# The name of the field that contains this facet's values
|
53
|
-
#
|
54
|
-
# ==== Returns
|
55
|
-
#
|
56
|
-
# Symbol:: The field name
|
57
|
-
#
|
58
|
-
def name
|
59
|
-
@field.name
|
60
|
-
end
|
61
|
-
|
62
|
-
# The rows returned for this facet.
|
63
|
-
#
|
64
|
-
# ==== Returns
|
65
|
-
#
|
66
|
-
# Array:: Collection of FacetRow objects, in the order returned by Solr
|
67
|
-
#
|
68
|
-
def rows
|
69
|
-
@rows ||=
|
70
|
-
begin
|
71
|
-
rows = []
|
72
|
-
@facet_values.each_slice(2) do |value, count|
|
73
|
-
rows << yield(row_value(value), count)
|
74
|
-
end
|
75
|
-
rows
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
#
|
81
|
-
# DateFacetData encapsulates facet date for date-range facets.
|
82
|
-
#
|
83
|
-
class DateFacetData < FieldFacetData
|
84
|
-
def initialize(facet_values, field)
|
85
|
-
@gap = facet_values.delete('gap')[/\+(\d+)SECONDS/,1].to_i
|
86
|
-
%w(start end).each { |key| facet_values.delete(key) }
|
87
|
-
super(facet_values.to_a.flatten, field)
|
88
|
-
end
|
89
|
-
|
90
|
-
#
|
91
|
-
# Get the rows of this date facet, which are instances of DateFacetRow.
|
92
|
-
# The rows will always be sorted in chronological order.
|
93
|
-
#
|
94
|
-
#--
|
95
|
-
#
|
96
|
-
# The date facet info comes back from Solr as a hash, so we need to sort
|
97
|
-
# it manually. FIXME this currently assumes we want to do a "lexical"
|
98
|
-
# sort, but we should support count sort as well, even if it's not a
|
99
|
-
# common use case.
|
100
|
-
#
|
101
|
-
def rows(&block)
|
102
|
-
super(&block).sort { |a, b| a.value.first <=> b.value.first }
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def row_value(value)
|
108
|
-
cast(value)..(cast(value) + @gap)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
#
|
113
|
-
# QueryFacetData encapsulates the data returned by a query facet.
|
114
|
-
#
|
115
|
-
class QueryFacetData < Abstract
|
116
|
-
def initialize(outgoing_query_facet, row_data) #:nodoc:
|
117
|
-
@outgoing_query_facet, @row_data = outgoing_query_facet, row_data
|
118
|
-
@field = @outgoing_query_facet.field
|
119
|
-
end
|
120
|
-
|
121
|
-
#
|
122
|
-
# Use the name defined by the user
|
123
|
-
#
|
124
|
-
def name
|
125
|
-
outgoing_query_facet.name
|
126
|
-
end
|
127
|
-
|
128
|
-
#
|
129
|
-
# Get the rows associated with this query facet. Returned rows are always
|
130
|
-
# ordered by count.
|
131
|
-
#
|
132
|
-
# ==== Returns
|
133
|
-
#
|
134
|
-
# Array:: Collection of QueryFacetRow objects, ordered by count
|
135
|
-
#
|
136
|
-
def rows
|
137
|
-
@rows ||=
|
138
|
-
begin
|
139
|
-
rows = []
|
140
|
-
options = @outgoing_query_facet.options
|
141
|
-
minimum_count =
|
142
|
-
if options[:zeros] then 0
|
143
|
-
elsif options[:minimum_count] then options[:minimum_count]
|
144
|
-
else 1
|
145
|
-
end
|
146
|
-
for outgoing_row in @outgoing_query_facet.rows
|
147
|
-
row_query = outgoing_row.to_boolean_phrase
|
148
|
-
if @row_data.has_key?(row_query)
|
149
|
-
row = yield(outgoing_row.label, @row_data[row_query])
|
150
|
-
rows << row if row.count >= minimum_count
|
151
|
-
end
|
152
|
-
end
|
153
|
-
if options[:sort] == :index || !options[:limit] && options[:sort] != :count
|
154
|
-
if rows.all? { |row| row.value.respond_to?(:<=>) }
|
155
|
-
rows.sort! { |x, y| x.value <=> y.value }
|
156
|
-
end
|
157
|
-
else
|
158
|
-
rows.sort! { |x, y| y.count <=> x.count }
|
159
|
-
end
|
160
|
-
if limit = options[:limit]
|
161
|
-
rows[0, limit]
|
162
|
-
else
|
163
|
-
rows
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
data/lib/sunspot/facet_row.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Sunspot
|
2
|
-
#
|
3
|
-
# InstantiatedFacet instances allow access to a model instance based on a
|
4
|
-
# primary key stored in facet rows' values. The rows are hydrated lazily, but
|
5
|
-
# all rows are hydrated the first time #instance is called on any of the rows.
|
6
|
-
#
|
7
|
-
# Instatiated facets are possible for fields which are defined with a
|
8
|
-
# :references option.
|
9
|
-
#
|
10
|
-
# The #rows method returns InstantiatedFacetRow objects.
|
11
|
-
#
|
12
|
-
class InstantiatedFacet < Facet
|
13
|
-
#
|
14
|
-
# Hydrate all rows for the facet. For data accessors that can efficiently
|
15
|
-
# batch load, this is more efficient than individually lazy-loading
|
16
|
-
# instances for each row, but allows us to still stay lazy and not do work
|
17
|
-
# in the persistent store if the instances are not needed.
|
18
|
-
#
|
19
|
-
def populate_instances! #:nodoc:
|
20
|
-
ids = rows.map { |row| row.value }
|
21
|
-
reference_class = Sunspot::Util.full_const_get(@facet_data.reference.to_s)
|
22
|
-
accessor = Adapters::DataAccessor.create(reference_class)
|
23
|
-
instance_map = accessor.load_all(ids).inject({}) do |map, instance|
|
24
|
-
map[Adapters::InstanceAdapter.adapt(instance).id] = instance
|
25
|
-
map
|
26
|
-
end
|
27
|
-
for row in rows
|
28
|
-
row.instance = instance_map[row.value]
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
#
|
33
|
-
# A collection of InstantiatedFacetRow objects
|
34
|
-
#
|
35
|
-
def rows
|
36
|
-
@facet_data.rows { |value, count| InstantiatedFacetRow.new(value, count, self) }
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module Sunspot
|
2
|
-
#
|
3
|
-
# InstantiatedFacetRow objects represent a single value for an instantiated
|
4
|
-
# facet. As well as the usual FacetRow methods, InstantedFacetRow objects
|
5
|
-
# provide access to the persistent object referenced by the row's value.
|
6
|
-
#
|
7
|
-
class InstantiatedFacetRow < FacetRow
|
8
|
-
attr_writer :instance #:nodoc:
|
9
|
-
|
10
|
-
def initialize(value, count, facet) #:nodoc:
|
11
|
-
super(value, count)
|
12
|
-
@facet = facet
|
13
|
-
end
|
14
|
-
|
15
|
-
#
|
16
|
-
# Get the persistent object referenced by this row's value. Instances are
|
17
|
-
# batch-lazy-loaded, which means that for a given facet, all of the
|
18
|
-
# instances are loaded the first time any row's instance is requested.
|
19
|
-
#
|
20
|
-
def instance
|
21
|
-
unless defined?(@instance)
|
22
|
-
@facet.populate_instances!
|
23
|
-
end
|
24
|
-
@instance
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Sunspot
|
2
|
-
module Query
|
3
|
-
class FulltextBaseQuery < BaseQuery #:nodoc:
|
4
|
-
def initialize(keywords, options, types, setup)
|
5
|
-
super(types, setup)
|
6
|
-
@keywords = keywords
|
7
|
-
|
8
|
-
if highlight_options = options.delete(:highlight)
|
9
|
-
set_highlight(highlight_options == true ? [] : highlight_options)
|
10
|
-
end
|
11
|
-
|
12
|
-
if fulltext_fields = options.delete(:fields)
|
13
|
-
Array(fulltext_fields).each do |field|
|
14
|
-
add_fulltext_field(field)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def text_fields(field_names)
|
23
|
-
field_names.inject([]) do |fields, name|
|
24
|
-
fields.concat(@setup.text_fields(name))
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
#
|
29
|
-
# Returns the names of text fields that should be queried in a keyword
|
30
|
-
# search. If specific fields are requested, use those; otherwise use the
|
31
|
-
# union of all fields configured for the types under search.
|
32
|
-
#
|
33
|
-
def query_fields
|
34
|
-
@query_fields ||=
|
35
|
-
begin
|
36
|
-
fulltext_fields =
|
37
|
-
@fulltext_fields || @setup.all_text_fields.map do |field|
|
38
|
-
TextFieldBoost.new(field)
|
39
|
-
end
|
40
|
-
fulltext_fields.map do |fulltext_field|
|
41
|
-
fulltext_field.to_boosted_field
|
42
|
-
end.join(' ')
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Sunspot
|
2
|
-
module Query
|
3
|
-
#
|
4
|
-
# QueryFacetRow objects encapsulate restrictions for a particular
|
5
|
-
# QueryFacet. They also contain a label attribute, which is used as the
|
6
|
-
# value for the search result's corresponding facet row object.
|
7
|
-
#
|
8
|
-
# See Query::Scope for the API provided.
|
9
|
-
#
|
10
|
-
class QueryFacetRow < Connective::Conjunction #:nodoc:
|
11
|
-
attr_reader :label
|
12
|
-
|
13
|
-
def initialize(label, setup)
|
14
|
-
super(setup)
|
15
|
-
@label = label
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Sunspot
|
2
|
-
module Query
|
3
|
-
#
|
4
|
-
# QueryFieldFacets are used for the "restricted field facet" feature, which
|
5
|
-
# allows an :only parameter for field facets, specifying a set of values in
|
6
|
-
# which the searcher is interested. Since Solr does not support this feature
|
7
|
-
# directly in field facets, build query facets that replicate field facet
|
8
|
-
# behavior.
|
9
|
-
#
|
10
|
-
class QueryFieldFacet < QueryFacet #:nodoc:
|
11
|
-
def initialize(field, values, options)
|
12
|
-
super(field.name, options)
|
13
|
-
@field = field
|
14
|
-
values.each do |value|
|
15
|
-
add_row(value).add_component(Restriction::EqualTo.new(field, value))
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|