UnderpantsGnome-sunspot 0.9.1.1
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 +39 -0
- data/LICENSE +18 -0
- data/README.rdoc +154 -0
- data/Rakefile +9 -0
- data/TODO +4 -0
- data/VERSION.yml +4 -0
- data/bin/sunspot-configure-solr +46 -0
- data/bin/sunspot-solr +62 -0
- data/lib/light_config.rb +40 -0
- data/lib/sunspot.rb +470 -0
- data/lib/sunspot/adapters.rb +265 -0
- data/lib/sunspot/composite_setup.rb +186 -0
- data/lib/sunspot/configuration.rb +38 -0
- data/lib/sunspot/data_extractor.rb +47 -0
- data/lib/sunspot/date_facet.rb +36 -0
- data/lib/sunspot/date_facet_row.rb +17 -0
- data/lib/sunspot/dsl.rb +3 -0
- data/lib/sunspot/dsl/field_query.rb +72 -0
- data/lib/sunspot/dsl/fields.rb +86 -0
- data/lib/sunspot/dsl/query.rb +59 -0
- data/lib/sunspot/dsl/query_facet.rb +31 -0
- data/lib/sunspot/dsl/restriction.rb +25 -0
- data/lib/sunspot/dsl/scope.rb +193 -0
- data/lib/sunspot/dsl/search.rb +30 -0
- data/lib/sunspot/facet.rb +51 -0
- data/lib/sunspot/facet_row.rb +34 -0
- data/lib/sunspot/field.rb +157 -0
- data/lib/sunspot/field_factory.rb +126 -0
- data/lib/sunspot/indexer.rb +127 -0
- data/lib/sunspot/instantiated_facet.rb +38 -0
- data/lib/sunspot/instantiated_facet_row.rb +12 -0
- data/lib/sunspot/query.rb +190 -0
- data/lib/sunspot/query/base_query.rb +90 -0
- data/lib/sunspot/query/connective.rb +77 -0
- data/lib/sunspot/query/dynamic_query.rb +69 -0
- data/lib/sunspot/query/field_facet.rb +149 -0
- data/lib/sunspot/query/field_query.rb +57 -0
- data/lib/sunspot/query/pagination.rb +39 -0
- data/lib/sunspot/query/query_facet.rb +72 -0
- data/lib/sunspot/query/query_facet_row.rb +19 -0
- data/lib/sunspot/query/restriction.rb +225 -0
- data/lib/sunspot/query/scope.rb +165 -0
- data/lib/sunspot/query/sort.rb +36 -0
- data/lib/sunspot/query/sort_composite.rb +33 -0
- data/lib/sunspot/query_facet.rb +33 -0
- data/lib/sunspot/query_facet_row.rb +21 -0
- data/lib/sunspot/schema.rb +165 -0
- data/lib/sunspot/search.rb +222 -0
- data/lib/sunspot/search/hit.rb +62 -0
- data/lib/sunspot/session.rb +201 -0
- data/lib/sunspot/setup.rb +271 -0
- data/lib/sunspot/type.rb +200 -0
- data/lib/sunspot/util.rb +164 -0
- data/solr/etc/jetty.xml +212 -0
- data/solr/etc/webdefault.xml +379 -0
- data/solr/lib/jetty-6.1.3.jar +0 -0
- data/solr/lib/jetty-util-6.1.3.jar +0 -0
- data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
- data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
- data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
- data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
- data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
- data/solr/solr/conf/elevate.xml +36 -0
- data/solr/solr/conf/protwords.txt +21 -0
- data/solr/solr/conf/schema.xml +50 -0
- data/solr/solr/conf/solrconfig.xml +696 -0
- data/solr/solr/conf/stopwords.txt +57 -0
- data/solr/solr/conf/synonyms.txt +31 -0
- data/solr/start.jar +0 -0
- data/solr/webapps/solr.war +0 -0
- data/spec/api/adapters_spec.rb +33 -0
- data/spec/api/build_search_spec.rb +918 -0
- data/spec/api/indexer_spec.rb +311 -0
- data/spec/api/query_spec.rb +153 -0
- data/spec/api/search_retrieval_spec.rb +325 -0
- data/spec/api/session_spec.rb +157 -0
- data/spec/api/spec_helper.rb +1 -0
- data/spec/api/sunspot_spec.rb +18 -0
- data/spec/integration/dynamic_fields_spec.rb +55 -0
- data/spec/integration/faceting_spec.rb +169 -0
- data/spec/integration/keyword_search_spec.rb +83 -0
- data/spec/integration/scoped_search_spec.rb +188 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/integration/stored_fields_spec.rb +10 -0
- data/spec/integration/test_pagination.rb +32 -0
- data/spec/mocks/adapters.rb +32 -0
- data/spec/mocks/blog.rb +3 -0
- data/spec/mocks/comment.rb +19 -0
- data/spec/mocks/connection.rb +84 -0
- data/spec/mocks/mock_adapter.rb +30 -0
- data/spec/mocks/mock_record.rb +41 -0
- data/spec/mocks/photo.rb +8 -0
- data/spec/mocks/post.rb +70 -0
- data/spec/mocks/user.rb +8 -0
- data/spec/spec_helper.rb +47 -0
- data/tasks/gemspec.rake +25 -0
- data/tasks/rcov.rake +28 -0
- data/tasks/rdoc.rake +21 -0
- data/tasks/schema.rake +19 -0
- data/tasks/spec.rake +24 -0
- data/tasks/todo.rake +4 -0
- data/templates/schema.xml.haml +24 -0
- metadata +245 -0
@@ -0,0 +1,222 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'search', 'hit')
|
2
|
+
|
3
|
+
module Sunspot
|
4
|
+
#
|
5
|
+
# This class encapsulates the results of a Solr search. It provides access
|
6
|
+
# to search results, total result count, facets, and pagination information.
|
7
|
+
# Instances of Search are returned by the Sunspot.search and
|
8
|
+
# Sunspot.new_search methods.
|
9
|
+
#
|
10
|
+
class Search
|
11
|
+
# Query information for this search. If you wish to build the query without
|
12
|
+
# using the search DSL, this method allows you to access the query API
|
13
|
+
# directly. See Sunspot#new_search for how to construct the search object
|
14
|
+
# in this case.
|
15
|
+
attr_reader :query
|
16
|
+
|
17
|
+
def initialize(connection, setup, query) #:nodoc:
|
18
|
+
@connection, @setup, @query = connection, setup, query
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Execute the search on the Solr instance and store the results. If you
|
23
|
+
# use Sunspot#search() to construct your searches, there is no need to call
|
24
|
+
# this method as it has already been called. If you use
|
25
|
+
# Sunspot#new_search(), you will need to call this method after building the
|
26
|
+
# query.
|
27
|
+
#
|
28
|
+
def execute!
|
29
|
+
params = @query.to_params
|
30
|
+
@solr_result = @connection.select(params)
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Get the collection of results as instantiated objects. If WillPaginate is
|
36
|
+
# available, the results will be a WillPaginate::Collection instance; if
|
37
|
+
# not, it will be a vanilla Array.
|
38
|
+
#
|
39
|
+
# ==== Returns
|
40
|
+
#
|
41
|
+
# WillPaginate::Collection or Array:: Instantiated result objects
|
42
|
+
#
|
43
|
+
def results
|
44
|
+
@results ||= if @query.page && defined?(WillPaginate::Collection)
|
45
|
+
WillPaginate::Collection.create(@query.page, @query.per_page, total) do |pager|
|
46
|
+
pager.replace(hits.map { |hit| hit.instance })
|
47
|
+
end
|
48
|
+
else
|
49
|
+
hits.map { |hit| hit.instance }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Access raw Solr result information. Returns a collection of Hit objects
|
55
|
+
# that contain the class name, primary key, keyword relevance score (if
|
56
|
+
# applicable), and any stored fields.
|
57
|
+
#
|
58
|
+
# ==== Returns
|
59
|
+
#
|
60
|
+
# Array:: Ordered collection of Hit objects
|
61
|
+
#
|
62
|
+
def hits
|
63
|
+
@hits ||= solr_response['docs'].map { |doc| Hit.new(doc, self) }
|
64
|
+
end
|
65
|
+
alias_method :raw_results, :hits
|
66
|
+
|
67
|
+
#
|
68
|
+
# The total number of documents matching the query parameters
|
69
|
+
#
|
70
|
+
# ==== Returns
|
71
|
+
#
|
72
|
+
# Integer:: Total matching documents
|
73
|
+
#
|
74
|
+
def total
|
75
|
+
@total ||= solr_response['numFound']
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Get the facet object for the given field. This field will need to have
|
80
|
+
# been requested as a field facet inside the search block.
|
81
|
+
#
|
82
|
+
# ==== Parameters
|
83
|
+
#
|
84
|
+
# field_name<Symbol>:: field name for which to get the facet
|
85
|
+
#
|
86
|
+
# ==== Returns
|
87
|
+
#
|
88
|
+
# Sunspot::Facet:: Facet object for the given field
|
89
|
+
#
|
90
|
+
def facet(field_name)
|
91
|
+
(@facets_cache ||= {})[field_name.to_sym] ||=
|
92
|
+
begin
|
93
|
+
query_facet(field_name) ||
|
94
|
+
begin
|
95
|
+
field = field(field_name)
|
96
|
+
date_facet(field) ||
|
97
|
+
begin
|
98
|
+
facet_class = field.reference ? InstantiatedFacet : Facet
|
99
|
+
facet_class.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Get the facet object for a given dynamic field. This dynamic field will
|
107
|
+
# need to have been requested as a field facet inside the search block.
|
108
|
+
#
|
109
|
+
# ==== Parameters
|
110
|
+
#
|
111
|
+
# base_name<Symbol>::
|
112
|
+
# Base name of the dynamic field definiton (as specified in the setup
|
113
|
+
# block)
|
114
|
+
# dynamic_name<Symbol>::
|
115
|
+
# Dynamic field name to facet on
|
116
|
+
#
|
117
|
+
# ==== Returns
|
118
|
+
#
|
119
|
+
# Sunspot::Facet:: Facet object for given dynamic field
|
120
|
+
#
|
121
|
+
# ==== Example
|
122
|
+
#
|
123
|
+
# search = Sunspot.search(Post) do
|
124
|
+
# dynamic :custom do
|
125
|
+
# facet :cuisine
|
126
|
+
# end
|
127
|
+
# end
|
128
|
+
# search.dynamic_facet(:custom, :cuisine)
|
129
|
+
# #=> Facet for the dynamic field :cuisine in the :custom field definition
|
130
|
+
#
|
131
|
+
def dynamic_facet(base_name, dynamic_name)
|
132
|
+
(@dynamic_facets_cache ||= {})[[base_name.to_sym, dynamic_name.to_sym]] ||=
|
133
|
+
begin
|
134
|
+
field = @setup.dynamic_field_factory(base_name).build(dynamic_name)
|
135
|
+
Facet.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Get the data accessor that will be used to load a particular class out of
|
141
|
+
# persistent storage. Data accessors can implement any methods that may be
|
142
|
+
# useful for refining how data is loaded out of storage. When building a
|
143
|
+
# search manually (e.g., using the Sunspot#new_search method), this should
|
144
|
+
# be used before calling #execute(). Use the
|
145
|
+
# Sunspot::DSL::Search#data_accessor_for method when building searches using
|
146
|
+
# the block DSL.
|
147
|
+
#
|
148
|
+
def data_accessor_for(clazz)
|
149
|
+
(@data_accessors ||= {})[clazz.name.to_sym] ||=
|
150
|
+
Adapters::DataAccessor.create(clazz)
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# Build this search using a DSL block.
|
155
|
+
#
|
156
|
+
def build(&block) #:nodoc:
|
157
|
+
Util.instance_eval_or_call(dsl, &block)
|
158
|
+
self
|
159
|
+
end
|
160
|
+
|
161
|
+
def populate_hits! #:nodoc:
|
162
|
+
type_hit_hash = Hash.new { |h, k| h[k] = [] }
|
163
|
+
id_hit_hash = {}
|
164
|
+
for hit in hits
|
165
|
+
type_hit_hash[hit.class_name] << hit
|
166
|
+
id_hit_hash[hit.primary_key] = hit
|
167
|
+
end
|
168
|
+
type_hit_hash.each_pair do |class_name, hits|
|
169
|
+
ids = hits.map { |hit| hit.primary_key }
|
170
|
+
for instance in data_accessor_for(Util.full_const_get(class_name)).load_all(ids)
|
171
|
+
hit = id_hit_hash[Adapters::InstanceAdapter.adapt(instance).id.to_s]
|
172
|
+
hit.instance = instance
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
|
179
|
+
def solr_response
|
180
|
+
@solr_response ||= @solr_result['response']
|
181
|
+
end
|
182
|
+
|
183
|
+
def doc_ids
|
184
|
+
@doc_ids ||= solr_response['docs'].map { |doc| doc['id'] }
|
185
|
+
end
|
186
|
+
|
187
|
+
def dsl
|
188
|
+
DSL::Search.new(self)
|
189
|
+
end
|
190
|
+
|
191
|
+
def raw_facet(field)
|
192
|
+
if field.type == Type::TimeType
|
193
|
+
@solr_result['facet_counts']['facet_dates'][field.indexed_name]
|
194
|
+
end || @solr_result['facet_counts']['facet_fields'][field.indexed_name]
|
195
|
+
end
|
196
|
+
|
197
|
+
def date_facet(field)
|
198
|
+
if field.type == Type::TimeType
|
199
|
+
if @solr_result['facet_counts'].has_key?('facet_dates')
|
200
|
+
if facet_result = @solr_result['facet_counts']['facet_dates'][field.indexed_name]
|
201
|
+
DateFacet.new(facet_result, field)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def query_facet(name)
|
208
|
+
if query_facet = @query.query_facet(name.to_sym)
|
209
|
+
if @solr_result['facet_counts'].has_key?('facet_queries')
|
210
|
+
QueryFacet.new(
|
211
|
+
query_facet,
|
212
|
+
@solr_result['facet_counts']['facet_queries']
|
213
|
+
)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def field(name)
|
219
|
+
@setup.field(name)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Sunspot
|
2
|
+
class Search
|
3
|
+
class Hit
|
4
|
+
SPECIAL_KEYS = Set.new(%w(id type score)) #:nodoc:
|
5
|
+
|
6
|
+
#
|
7
|
+
# Primary key of object associated with this hit, as string.
|
8
|
+
#
|
9
|
+
attr_reader :primary_key
|
10
|
+
#
|
11
|
+
# Class name of object associated with this hit, as string.
|
12
|
+
#
|
13
|
+
attr_reader :class_name
|
14
|
+
#
|
15
|
+
# Keyword relevance score associated with this result. Nil if this hit
|
16
|
+
# is not from a keyword search.
|
17
|
+
#
|
18
|
+
attr_reader :score
|
19
|
+
|
20
|
+
attr_writer :instance #:nodoc:
|
21
|
+
|
22
|
+
def initialize(raw_hit, search) #:nodoc:
|
23
|
+
@class_name, @primary_key = *raw_hit['id'].match(/([^ ]+) (.+)/)[1..2]
|
24
|
+
@score = raw_hit['score']
|
25
|
+
@search = search
|
26
|
+
@stored_values = raw_hit
|
27
|
+
@stored_cache = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Retrieve stored field value. For any attribute field configured with
|
32
|
+
# :stored => true, the Hit object will contain the stored value for
|
33
|
+
# that field. The value of this field will be typecast according to the
|
34
|
+
# type of the field.
|
35
|
+
#
|
36
|
+
# ==== Parameters
|
37
|
+
#
|
38
|
+
# field_name<Symbol>::
|
39
|
+
# The name of the field for which to retrieve the stored value.
|
40
|
+
#
|
41
|
+
def stored(field_name)
|
42
|
+
@stored_cache[field_name.to_sym] ||=
|
43
|
+
begin
|
44
|
+
field = Sunspot::Setup.for(@class_name).field(field_name)
|
45
|
+
field.cast(@stored_values[field.indexed_name])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Retrieve the instance associated with this hit. This is lazy-loaded, but
|
51
|
+
# the first time it is called on any hit, all the hits for the search will
|
52
|
+
# load their instances using the adapter's #load_all method.
|
53
|
+
#
|
54
|
+
def instance
|
55
|
+
if @instance.nil?
|
56
|
+
@search.populate_hits!
|
57
|
+
end
|
58
|
+
@instance
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
module Sunspot
|
2
|
+
#
|
3
|
+
# A Sunspot session encapsulates a connection to Solr and a set of
|
4
|
+
# configuration choices. Though users of Sunspot may manually instantiate
|
5
|
+
# Session objects, in the general case it's easier to use the singleton
|
6
|
+
# stored in the Sunspot module. Since the Sunspot module provides all of
|
7
|
+
# the instance methods of Session as class methods, they are not documented
|
8
|
+
# again here.
|
9
|
+
#
|
10
|
+
class Session
|
11
|
+
class <<self
|
12
|
+
attr_writer :connection_class #:nodoc:
|
13
|
+
|
14
|
+
#
|
15
|
+
# For testing purposes
|
16
|
+
#
|
17
|
+
def connection_class #:nodoc:
|
18
|
+
@connection_class ||= RSolr::Connection
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Sunspot::Configuration object for this session
|
24
|
+
#
|
25
|
+
attr_reader :config
|
26
|
+
|
27
|
+
#
|
28
|
+
# Sessions are initialized with a Sunspot configuration and a Solr
|
29
|
+
# connection. Usually you will want to stick with the default arguments
|
30
|
+
# when instantiating your own sessions.
|
31
|
+
#
|
32
|
+
def initialize(config = Configuration.build, connection = nil)
|
33
|
+
@config = config
|
34
|
+
yield(@config) if block_given?
|
35
|
+
@connection = connection
|
36
|
+
@updates = 0
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# See Sunspot.new_search
|
41
|
+
#
|
42
|
+
def new_search(*types)
|
43
|
+
types.flatten!
|
44
|
+
setup =
|
45
|
+
if types.length == 1
|
46
|
+
Setup.for(types.first)
|
47
|
+
else
|
48
|
+
CompositeSetup.for(types)
|
49
|
+
end
|
50
|
+
Search.new(connection, setup, Query::Query.new(setup, @config))
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# See Sunspot.search
|
55
|
+
#
|
56
|
+
def search(*types, &block)
|
57
|
+
options = types.last.is_a?(Hash) ? types.pop : {}
|
58
|
+
search = new_search(*types)
|
59
|
+
search.build(&block) if block
|
60
|
+
search.query.options = options
|
61
|
+
search.execute!
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# See Sunspot.index
|
66
|
+
#
|
67
|
+
def index(*objects)
|
68
|
+
objects.flatten!
|
69
|
+
@updates += objects.length
|
70
|
+
indexer.add(objects)
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# See Sunspot.index!
|
75
|
+
#
|
76
|
+
def index!(*objects)
|
77
|
+
index(*objects)
|
78
|
+
commit
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# See Sunspot.commit
|
83
|
+
#
|
84
|
+
def commit
|
85
|
+
@updates = 0
|
86
|
+
connection.commit
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# See Sunspot.remove
|
91
|
+
#
|
92
|
+
def remove(*objects)
|
93
|
+
objects.flatten!
|
94
|
+
@updates += objects.length
|
95
|
+
for object in objects
|
96
|
+
indexer.remove(object)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# See Sunspot.remove!
|
102
|
+
#
|
103
|
+
def remove!(*objects)
|
104
|
+
remove(*objects)
|
105
|
+
commit
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# See Sunspot.remove_by_id
|
110
|
+
#
|
111
|
+
def remove_by_id(clazz, id)
|
112
|
+
class_name =
|
113
|
+
if clazz.is_a?(Class)
|
114
|
+
clazz.name
|
115
|
+
else
|
116
|
+
clazz.to_s
|
117
|
+
end
|
118
|
+
indexer.remove_by_id(class_name, id)
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# See Sunspot.remove_by_id!
|
123
|
+
#
|
124
|
+
def remove_by_id!(clazz, id)
|
125
|
+
remove_by_id(clazz, id)
|
126
|
+
commit
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# See Sunspot.remove_all
|
131
|
+
#
|
132
|
+
def remove_all(*classes)
|
133
|
+
classes.flatten!
|
134
|
+
if classes.empty?
|
135
|
+
@updates += 1
|
136
|
+
Indexer.remove_all(connection)
|
137
|
+
else
|
138
|
+
@updates += classes.length
|
139
|
+
for clazz in classes
|
140
|
+
indexer.remove_all(clazz)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# See Sunspot.remove_all!
|
147
|
+
#
|
148
|
+
def remove_all!(*classes)
|
149
|
+
remove_all(*classes)
|
150
|
+
commit
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# See Sunspot.dirty?
|
155
|
+
#
|
156
|
+
def dirty?
|
157
|
+
@updates > 0
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# See Sunspot.commit_if_dirty
|
162
|
+
#
|
163
|
+
def commit_if_dirty
|
164
|
+
commit if dirty?
|
165
|
+
end
|
166
|
+
|
167
|
+
#
|
168
|
+
# See Sunspot.batch
|
169
|
+
#
|
170
|
+
def batch
|
171
|
+
indexer.start_batch
|
172
|
+
yield
|
173
|
+
indexer.flush_batch
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
#
|
179
|
+
# Retrieve the Solr connection for this session, creating one if it does not
|
180
|
+
# already exist.
|
181
|
+
#
|
182
|
+
# ==== Returns
|
183
|
+
#
|
184
|
+
# Solr::Connection:: The connection for this session
|
185
|
+
#
|
186
|
+
def connection
|
187
|
+
@connection ||=
|
188
|
+
begin
|
189
|
+
connection = self.class.connection_class.new(
|
190
|
+
RSolr::Adapter::HTTP.new(:url => config.solr.url)
|
191
|
+
)
|
192
|
+
connection.adapter.connector.adapter_name = config.http_client
|
193
|
+
connection
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def indexer
|
198
|
+
@indexer ||= Indexer.new(connection)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|