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