sunspot 2.0.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/Appraisals +7 -0
  5. data/Gemfile +0 -2
  6. data/History.txt +10 -0
  7. data/lib/sunspot.rb +55 -17
  8. data/lib/sunspot/adapters.rb +68 -18
  9. data/lib/sunspot/batcher.rb +1 -1
  10. data/lib/sunspot/configuration.rb +4 -2
  11. data/lib/sunspot/data_extractor.rb +36 -6
  12. data/lib/sunspot/dsl.rb +4 -3
  13. data/lib/sunspot/dsl/adjustable.rb +2 -2
  14. data/lib/sunspot/dsl/field_query.rb +69 -16
  15. data/lib/sunspot/dsl/field_stats.rb +25 -0
  16. data/lib/sunspot/dsl/fields.rb +28 -8
  17. data/lib/sunspot/dsl/fulltext.rb +9 -1
  18. data/lib/sunspot/dsl/group.rb +118 -0
  19. data/lib/sunspot/dsl/paginatable.rb +4 -1
  20. data/lib/sunspot/dsl/scope.rb +19 -10
  21. data/lib/sunspot/dsl/search.rb +1 -1
  22. data/lib/sunspot/dsl/spellcheckable.rb +14 -0
  23. data/lib/sunspot/dsl/standard_query.rb +63 -35
  24. data/lib/sunspot/field.rb +76 -4
  25. data/lib/sunspot/field_factory.rb +60 -11
  26. data/lib/sunspot/indexer.rb +70 -18
  27. data/lib/sunspot/query.rb +5 -4
  28. data/lib/sunspot/query/abstract_field_facet.rb +0 -2
  29. data/lib/sunspot/query/abstract_fulltext.rb +76 -0
  30. data/lib/sunspot/query/abstract_json_field_facet.rb +70 -0
  31. data/lib/sunspot/query/bbox.rb +5 -1
  32. data/lib/sunspot/query/common_query.rb +31 -6
  33. data/lib/sunspot/query/composite_fulltext.rb +58 -8
  34. data/lib/sunspot/query/date_field_json_facet.rb +25 -0
  35. data/lib/sunspot/query/dismax.rb +25 -71
  36. data/lib/sunspot/query/field_json_facet.rb +19 -0
  37. data/lib/sunspot/query/field_list.rb +15 -0
  38. data/lib/sunspot/query/field_stats.rb +61 -0
  39. data/lib/sunspot/query/function_query.rb +1 -2
  40. data/lib/sunspot/query/geo.rb +1 -1
  41. data/lib/sunspot/query/geofilt.rb +8 -3
  42. data/lib/sunspot/query/group.rb +46 -0
  43. data/lib/sunspot/query/group_query.rb +17 -0
  44. data/lib/sunspot/query/join.rb +88 -0
  45. data/lib/sunspot/query/more_like_this.rb +1 -1
  46. data/lib/sunspot/query/pagination.rb +12 -4
  47. data/lib/sunspot/query/range_json_facet.rb +28 -0
  48. data/lib/sunspot/query/restriction.rb +99 -13
  49. data/lib/sunspot/query/sort.rb +41 -0
  50. data/lib/sunspot/query/sort_composite.rb +7 -0
  51. data/lib/sunspot/query/spellcheck.rb +19 -0
  52. data/lib/sunspot/query/standard_query.rb +24 -2
  53. data/lib/sunspot/query/text_field_boost.rb +1 -3
  54. data/lib/sunspot/schema.rb +12 -3
  55. data/lib/sunspot/search.rb +4 -2
  56. data/lib/sunspot/search/abstract_search.rb +93 -43
  57. data/lib/sunspot/search/cursor_paginated_collection.rb +32 -0
  58. data/lib/sunspot/search/field_facet.rb +4 -4
  59. data/lib/sunspot/search/field_json_facet.rb +33 -0
  60. data/lib/sunspot/search/field_stats.rb +21 -0
  61. data/lib/sunspot/search/hit.rb +6 -1
  62. data/lib/sunspot/search/hit_enumerable.rb +4 -1
  63. data/lib/sunspot/search/json_facet_row.rb +40 -0
  64. data/lib/sunspot/search/json_facet_stats.rb +23 -0
  65. data/lib/sunspot/search/paginated_collection.rb +1 -0
  66. data/lib/sunspot/search/query_group.rb +74 -0
  67. data/lib/sunspot/search/standard_search.rb +70 -3
  68. data/lib/sunspot/search/stats_facet.rb +25 -0
  69. data/lib/sunspot/search/stats_json_row.rb +82 -0
  70. data/lib/sunspot/search/stats_row.rb +68 -0
  71. data/lib/sunspot/session.rb +62 -37
  72. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +6 -4
  73. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +16 -8
  74. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +2 -2
  75. data/lib/sunspot/session_proxy/retry_5xx_session_proxy.rb +1 -1
  76. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +4 -2
  77. data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +1 -1
  78. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +6 -4
  79. data/lib/sunspot/setup.rb +42 -0
  80. data/lib/sunspot/type.rb +20 -0
  81. data/lib/sunspot/util.rb +78 -14
  82. data/lib/sunspot/version.rb +1 -1
  83. data/spec/api/adapters_spec.rb +40 -15
  84. data/spec/api/batcher_spec.rb +15 -15
  85. data/spec/api/binding_spec.rb +3 -3
  86. data/spec/api/class_set_spec.rb +6 -6
  87. data/spec/api/data_extractor_spec.rb +39 -0
  88. data/spec/api/hit_enumerable_spec.rb +32 -9
  89. data/spec/api/indexer/attributes_spec.rb +35 -30
  90. data/spec/api/indexer/batch_spec.rb +8 -7
  91. data/spec/api/indexer/dynamic_fields_spec.rb +8 -8
  92. data/spec/api/indexer/fixed_fields_spec.rb +16 -11
  93. data/spec/api/indexer/fulltext_spec.rb +8 -8
  94. data/spec/api/indexer/removal_spec.rb +24 -14
  95. data/spec/api/indexer_spec.rb +2 -2
  96. data/spec/api/query/advanced_manipulation_examples.rb +3 -3
  97. data/spec/api/query/connectives_examples.rb +26 -14
  98. data/spec/api/query/dsl_spec.rb +24 -6
  99. data/spec/api/query/dynamic_fields_examples.rb +18 -18
  100. data/spec/api/query/faceting_examples.rb +80 -61
  101. data/spec/api/query/fulltext_examples.rb +194 -40
  102. data/spec/api/query/function_spec.rb +116 -13
  103. data/spec/api/query/geo_examples.rb +8 -12
  104. data/spec/api/query/group_spec.rb +27 -5
  105. data/spec/api/query/highlighting_examples.rb +26 -26
  106. data/spec/api/query/join_spec.rb +19 -0
  107. data/spec/api/query/more_like_this_spec.rb +40 -27
  108. data/spec/api/query/ordering_pagination_examples.rb +37 -23
  109. data/spec/api/query/scope_examples.rb +39 -39
  110. data/spec/api/query/spatial_examples.rb +3 -3
  111. data/spec/api/query/spellcheck_examples.rb +20 -0
  112. data/spec/api/query/standard_spec.rb +3 -1
  113. data/spec/api/query/stats_examples.rb +66 -0
  114. data/spec/api/query/text_field_scoping_examples.rb +5 -5
  115. data/spec/api/query/types_spec.rb +4 -4
  116. data/spec/api/search/cursor_paginated_collection_spec.rb +35 -0
  117. data/spec/api/search/dynamic_fields_spec.rb +4 -4
  118. data/spec/api/search/faceting_spec.rb +55 -52
  119. data/spec/api/search/highlighting_spec.rb +7 -7
  120. data/spec/api/search/hits_spec.rb +43 -29
  121. data/spec/api/search/paginated_collection_spec.rb +19 -18
  122. data/spec/api/search/results_spec.rb +13 -13
  123. data/spec/api/search/search_spec.rb +3 -3
  124. data/spec/api/search/stats_spec.rb +94 -0
  125. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +23 -16
  126. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +16 -4
  127. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +10 -6
  128. data/spec/api/session_proxy/retry_5xx_session_proxy_spec.rb +11 -11
  129. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +15 -14
  130. data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +3 -3
  131. data/spec/api/session_proxy/spec_helper.rb +1 -1
  132. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +40 -26
  133. data/spec/api/session_spec.rb +78 -38
  134. data/spec/api/sunspot_spec.rb +7 -4
  135. data/spec/helpers/integration_helper.rb +11 -1
  136. data/spec/helpers/query_helper.rb +1 -1
  137. data/spec/helpers/search_helper.rb +30 -0
  138. data/spec/integration/atomic_updates_spec.rb +58 -0
  139. data/spec/integration/dynamic_fields_spec.rb +31 -20
  140. data/spec/integration/faceting_spec.rb +252 -39
  141. data/spec/integration/field_grouping_spec.rb +47 -15
  142. data/spec/integration/field_lists_spec.rb +57 -0
  143. data/spec/integration/geospatial_spec.rb +34 -8
  144. data/spec/integration/highlighting_spec.rb +8 -8
  145. data/spec/integration/indexing_spec.rb +7 -6
  146. data/spec/integration/join_spec.rb +45 -0
  147. data/spec/integration/keyword_search_spec.rb +68 -38
  148. data/spec/integration/local_search_spec.rb +4 -4
  149. data/spec/integration/more_like_this_spec.rb +7 -7
  150. data/spec/integration/scoped_search_spec.rb +193 -74
  151. data/spec/integration/spellcheck_spec.rb +119 -0
  152. data/spec/integration/stats_spec.rb +88 -0
  153. data/spec/integration/stored_fields_spec.rb +1 -1
  154. data/spec/integration/test_pagination.rb +4 -4
  155. data/spec/integration/unicode_spec.rb +1 -1
  156. data/spec/mocks/adapters.rb +36 -0
  157. data/spec/mocks/connection.rb +5 -3
  158. data/spec/mocks/photo.rb +32 -1
  159. data/spec/mocks/post.rb +18 -3
  160. data/spec/spec_helper.rb +13 -8
  161. data/sunspot.gemspec +6 -4
  162. data/tasks/rdoc.rake +22 -14
  163. metadata +101 -44
  164. data/lib/sunspot/dsl/field_group.rb +0 -57
  165. data/lib/sunspot/query/field_group.rb +0 -37
@@ -0,0 +1,68 @@
1
+ module Sunspot
2
+ module Search
3
+ class StatsRow
4
+ attr_reader :data, :value
5
+ attr_writer :instance #:nodoc:
6
+
7
+ def initialize(data, facet = nil, value = nil) #:nodoc:
8
+ @data, @facet, @value = data, facet, value
9
+ @facet_fields = []
10
+ end
11
+
12
+ def min
13
+ data['min']
14
+ end
15
+
16
+ def max
17
+ data['max']
18
+ end
19
+
20
+ def count
21
+ data['count']
22
+ end
23
+
24
+ def sum
25
+ data['sum']
26
+ end
27
+
28
+ def missing
29
+ data['missing']
30
+ end
31
+
32
+ def sum_of_squares
33
+ data['sumOfSquares']
34
+ end
35
+
36
+ def mean
37
+ data['mean']
38
+ end
39
+
40
+ def standard_deviation
41
+ data['stddev']
42
+ end
43
+
44
+ def facet name
45
+ facets.find { |facet| facet.field.name == name.to_sym }
46
+ end
47
+
48
+ def facets
49
+ @facets ||= @facet_fields.map do |field|
50
+ StatsFacet.new(field, data['facets'][field.indexed_name])
51
+ end
52
+ end
53
+
54
+ def instance
55
+ if !defined?(@instance)
56
+ @facet.populate_instances
57
+ end
58
+ @instance
59
+ end
60
+
61
+ def inspect
62
+ "<Sunspot::Search::StatsRow:#{value.inspect} min=#{min} max=#{max}"\
63
+ " count=#{self.count} sum=#{sum} missing=#{missing} sum_of_squares=#{sum_of_squares}"\
64
+ " mean=#{mean} standard_deviation=#{standard_deviation}>"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,5 +1,5 @@
1
1
  module Sunspot
2
- #
2
+ #
3
3
  # A Sunspot session encapsulates a connection to Solr and a set of
4
4
  # configuration choices. Though users of Sunspot may manually instantiate
5
5
  # Session objects, in the general case it's easier to use the singleton
@@ -10,8 +10,8 @@ module Sunspot
10
10
  class Session
11
11
  class <<self
12
12
  attr_writer :connection_class #:nodoc:
13
-
14
- #
13
+
14
+ #
15
15
  # For testing purposes
16
16
  #
17
17
  def connection_class #:nodoc:
@@ -19,12 +19,12 @@ module Sunspot
19
19
  end
20
20
  end
21
21
 
22
- #
22
+ #
23
23
  # Sunspot::Configuration object for this session
24
24
  #
25
25
  attr_reader :config
26
26
 
27
- #
27
+ #
28
28
  # Sessions are initialized with a Sunspot configuration and a Solr
29
29
  # connection. Usually you will want to stick with the default arguments
30
30
  # when instantiating your own sessions.
@@ -36,7 +36,7 @@ module Sunspot
36
36
  @deletes = @adds = 0
37
37
  end
38
38
 
39
- #
39
+ #
40
40
  # See Sunspot.new_search
41
41
  #
42
42
  def new_search(*types, &block)
@@ -59,7 +59,7 @@ module Sunspot
59
59
  search.execute
60
60
  end
61
61
 
62
- #
62
+ #
63
63
  # See Sunspot.new_more_like_this
64
64
  #
65
65
  def new_more_like_this(object, *types, &block)
@@ -91,7 +91,7 @@ module Sunspot
91
91
  indexer.add(objects)
92
92
  end
93
93
 
94
- #
94
+ #
95
95
  # See Sunspot.index!
96
96
  #
97
97
  def index!(*objects)
@@ -99,12 +99,28 @@ module Sunspot
99
99
  commit
100
100
  end
101
101
 
102
+ #
103
+ # See Sunspot.atomic_update
104
+ #
105
+ def atomic_update(clazz, updates = {})
106
+ @adds += updates.keys.length
107
+ indexer.add_atomic_update(clazz, updates)
108
+ end
109
+
110
+ #
111
+ # See Sunspot.atomic_update!
112
+ #
113
+ def atomic_update!(clazz, updates = {})
114
+ atomic_update(clazz, updates)
115
+ commit
116
+ end
117
+
102
118
  #
103
119
  # See Sunspot.commit
104
120
  #
105
- def commit
121
+ def commit(soft_commit = false)
106
122
  @adds = @deletes = 0
107
- connection.commit
123
+ connection.commit :commit_attributes => {:softCommit => soft_commit}
108
124
  end
109
125
 
110
126
  #
@@ -115,7 +131,7 @@ module Sunspot
115
131
  connection.optimize
116
132
  end
117
133
 
118
- #
134
+ #
119
135
  # See Sunspot.remove
120
136
  #
121
137
  def remove(*objects, &block)
@@ -139,32 +155,32 @@ module Sunspot
139
155
  end
140
156
  end
141
157
 
142
- #
158
+ #
143
159
  # See Sunspot.remove!
144
160
  #
145
- def remove!(*objects)
146
- remove(*objects)
161
+ def remove!(*objects, &block)
162
+ remove(*objects, &block)
147
163
  commit
148
164
  end
149
165
 
150
- #
166
+ #
151
167
  # See Sunspot.remove_by_id
152
168
  #
153
- def remove_by_id(clazz, id)
169
+ def remove_by_id(clazz, *ids)
154
170
  class_name =
155
171
  if clazz.is_a?(Class)
156
172
  clazz.name
157
173
  else
158
174
  clazz.to_s
159
175
  end
160
- indexer.remove_by_id(class_name, id)
176
+ indexer.remove_by_id(class_name, ids)
161
177
  end
162
178
 
163
- #
179
+ #
164
180
  # See Sunspot.remove_by_id!
165
181
  #
166
- def remove_by_id!(clazz, id)
167
- remove_by_id(clazz, id)
182
+ def remove_by_id!(clazz, *ids)
183
+ remove_by_id(clazz, ids)
168
184
  commit
169
185
  end
170
186
 
@@ -182,7 +198,7 @@ module Sunspot
182
198
  end
183
199
  end
184
200
 
185
- #
201
+ #
186
202
  # See Sunspot.remove_all!
187
203
  #
188
204
  def remove_all!(*classes)
@@ -190,35 +206,35 @@ module Sunspot
190
206
  commit
191
207
  end
192
208
 
193
- #
209
+ #
194
210
  # See Sunspot.dirty?
195
211
  #
196
212
  def dirty?
197
213
  (@deletes + @adds) > 0
198
214
  end
199
215
 
200
- #
216
+ #
201
217
  # See Sunspot.commit_if_dirty
202
218
  #
203
- def commit_if_dirty
204
- commit if dirty?
219
+ def commit_if_dirty(soft_commit = false)
220
+ commit soft_commit if dirty?
205
221
  end
206
-
207
- #
222
+
223
+ #
208
224
  # See Sunspot.delete_dirty?
209
225
  #
210
226
  def delete_dirty?
211
227
  @deletes > 0
212
228
  end
213
229
 
214
- #
230
+ #
215
231
  # See Sunspot.commit_if_delete_dirty
216
232
  #
217
- def commit_if_delete_dirty
218
- commit if delete_dirty?
233
+ def commit_if_delete_dirty(soft_commit = false)
234
+ commit soft_commit if delete_dirty?
219
235
  end
220
-
221
- #
236
+
237
+ #
222
238
  # See Sunspot.batch
223
239
  #
224
240
  def batch
@@ -229,7 +245,7 @@ module Sunspot
229
245
 
230
246
  private
231
247
 
232
- #
248
+ #
233
249
  # Retrieve the Solr connection for this session, creating one if it does not
234
250
  # already exist.
235
251
  #
@@ -238,10 +254,13 @@ module Sunspot
238
254
  # RSolr::Connection::Base:: The connection for this session
239
255
  #
240
256
  def connection
241
- @connection ||=
242
- self.class.connection_class.connect(:url => config.solr.url,
243
- :read_timeout => config.solr.read_timeout,
244
- :open_timeout => config.solr.open_timeout)
257
+ @connection ||= self.class.connection_class.connect(
258
+ url: config.solr.url,
259
+ read_timeout: config.solr.read_timeout,
260
+ open_timeout: config.solr.open_timeout,
261
+ proxy: config.solr.proxy,
262
+ update_format: update_format_generator
263
+ )
245
264
  end
246
265
 
247
266
  def indexer
@@ -258,5 +277,11 @@ module Sunspot
258
277
  CompositeSetup.for(types)
259
278
  end
260
279
  end
280
+
281
+ def update_format_generator
282
+ if config.solr.update_format && RSolr.version.to_i > 1
283
+ config.solr.update_format.downcase.to_sym == :json ? RSolr::JSON::Generator : RSolr::Xml::Generator
284
+ end
285
+ end
261
286
  end
262
287
  end
@@ -23,15 +23,17 @@ module Sunspot
23
23
  #
24
24
  # See Sunspot.remove_by_id
25
25
  #
26
- def remove_by_id(clazz, id)
27
- session_for_class(clazz).remove_by_id(clazz, id)
26
+ def remove_by_id(clazz, *ids)
27
+ ids.flatten!
28
+ session_for_class(clazz).remove_by_id(clazz, ids)
28
29
  end
29
30
 
30
31
  #
31
32
  # See Sunspot.remove_by_id!
32
33
  #
33
- def remove_by_id!(clazz, id)
34
- session_for_class(clazz).remove_by_id!(clazz, id)
34
+ def remove_by_id!(clazz, *ids)
35
+ ids.flatten!
36
+ session_for_class(clazz).remove_by_id!(clazz, ids)
35
37
  end
36
38
 
37
39
  #
@@ -45,23 +45,31 @@ module Sunspot
45
45
  #
46
46
  # See Sunspot.remove_by_id
47
47
  #
48
- def remove_by_id(clazz, id)
49
- session_for_index_id(
50
- Adapters::InstanceAdapter.index_id_for(clazz, id)
51
- ).remove_by_id(clazz, id)
48
+ def remove_by_id(clazz, *ids)
49
+ ids.flatten!
50
+ ids_by_session(clazz, ids).each do |session, ids|
51
+ session.remove_by_id(clazz, ids)
52
+ end
52
53
  end
53
54
 
54
55
  #
55
56
  # See Sunspot.remove_by_id!
56
57
  #
57
- def remove_by_id!(clazz, id)
58
- session_for_index_id(
59
- Adapters::InstanceAdapter.index_id_for(clazz, id)
60
- ).remove_by_id!(clazz, id)
58
+ def remove_by_id!(clazz, *ids)
59
+ ids.flatten!
60
+ ids_by_session(clazz, ids).each do |session, ids|
61
+ session.remove_by_id!(clazz, ids)
62
+ end
61
63
  end
62
64
 
63
65
  private
64
66
 
67
+ def ids_by_session(clazz, ids)
68
+ ids.group_by do |id|
69
+ session_for_index_id(Adapters::InstanceAdapter.index_id_for(clazz, id))
70
+ end
71
+ end
72
+
65
73
  def session_for_index_id(index_id)
66
74
  @sessions[id_hash(index_id) % @sessions.length]
67
75
  end
@@ -19,8 +19,8 @@ module Sunspot
19
19
 
20
20
  delegate :batch, :commit, :commit_if_delete_dirty, :commit_if_dirty,
21
21
  :config, :delete_dirty?, :dirty?, :index, :index!, :optimize, :remove,
22
- :remove!, :remove_all, :remove_all!, :remove_by_id,
23
- :remove_by_id!, :to => :master_session
22
+ :remove!, :remove_all, :remove_all!, :remove_by_id, :remove_by_id!,
23
+ :atomic_update, :atomic_update!, :to => :master_session
24
24
  delegate :new_search, :search, :new_more_like_this, :more_like_this, :to => :slave_session
25
25
 
26
26
  def initialize(master_session, slave_session)
@@ -59,7 +59,7 @@ module Sunspot
59
59
 
60
60
  delegate :batch, :commit, :commit_if_dirty, :commit_if_delete_dirty,
61
61
  :dirty?, :index!, :index, :optimize, :remove!, :remove, :remove_all!,
62
- :remove_all, :remove_by_id!, :remove_by_id,
62
+ :remove_all, :remove_by_id!, :remove_by_id, :atomic_update, :atomic_update!,
63
63
  :to => :retry_handler
64
64
 
65
65
  end
@@ -27,9 +27,11 @@ module Sunspot
27
27
  # * remove_by_id!
28
28
  # * remove_all with an argument
29
29
  # * remove_all! with an argument
30
+ # * atomic_update with arguments
31
+ # * atomic_update! with arguments
30
32
  #
31
33
  class ShardingSessionProxy < AbstractSessionProxy
32
- not_supported :batch, :config, :remove_by_id, :remove_by_id!
34
+ not_supported :batch, :config, :remove_by_id, :remove_by_id!, :atomic_update, :atomic_update!
33
35
 
34
36
  #
35
37
  # +search_session+ is the session that should be used for searching.
@@ -70,7 +72,7 @@ module Sunspot
70
72
  using_sharded_session(objects) { |session, group| session.index!(group) }
71
73
  end
72
74
 
73
- #
75
+ #
74
76
  # See Sunspot.remove
75
77
  #
76
78
  def remove(*objects)
@@ -22,7 +22,7 @@ module Sunspot
22
22
  SUPPORTED_METHODS = [
23
23
  :batch, :commit, :commit_if_dirty, :commit_if_delete_dirty, :dirty?,
24
24
  :index!, :index, :optimize, :remove!, :remove, :remove_all!, :remove_all,
25
- :remove_by_id!, :remove_by_id
25
+ :remove_by_id!, :remove_by_id, :atomic_update, :atomic_update!
26
26
  ]
27
27
 
28
28
  SUPPORTED_METHODS.each do |method|
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), 'abstract_session_proxy')
3
3
 
4
4
  module Sunspot
5
5
  module SessionProxy
6
- #
6
+ #
7
7
  # This class implements a session proxy that creates a different Session
8
8
  # object for each thread. Any multithreaded application should use this
9
9
  # proxy.
@@ -17,14 +17,16 @@ module Sunspot
17
17
  attr_reader :config
18
18
  @@next_id = 0
19
19
 
20
- delegate :batch, :commit, :commit_if_delete_dirty, :commit_if_dirty, :delete_dirty?, :dirty?, :index, :index!, :new_search, :optimize, :remove, :remove!, :remove_all, :remove_all!, :remove_by_id, :remove_by_id!, :search, :more_like_this, :new_more_like_this, :to => :session
20
+ delegate :batch, :commit, :commit_if_delete_dirty, :commit_if_dirty, :delete_dirty?, :dirty?, :index, :index!,
21
+ :new_search, :optimize, :remove, :remove!, :remove_all, :remove_all!, :remove_by_id, :remove_by_id!,
22
+ :search, :more_like_this, :new_more_like_this, :atomic_update, :atomic_update!, :to => :session
21
23
 
22
- #
24
+ #
23
25
  # Optionally pass an existing Sunspot::Configuration object. If none is
24
26
  # passed, a default configuration is used; it can then be modified using
25
27
  # the #config attribute.
26
28
  #
27
- def initialize(config = Sunspot::Configuration.new)
29
+ def initialize(config = Sunspot::Configuration.build)
28
30
  @config = config
29
31
  ObjectSpace.define_finalizer(self, FINALIZER)
30
32
  end
data/lib/sunspot/setup.rb CHANGED
@@ -15,6 +15,7 @@ module Sunspot
15
15
  @more_like_this_field_factories_cache = Hash.new { |h, k| h[k] = [] }
16
16
  @dsl = DSL::Fields.new(self)
17
17
  @document_boost_extractor = nil
18
+ @id_prefix_extractor = nil
18
19
  add_field_factory(:class, Type::ClassType.instance)
19
20
  end
20
21
 
@@ -38,6 +39,17 @@ module Sunspot
38
39
  end
39
40
  end
40
41
 
42
+ def add_join_field_factory(name, type, options = {}, &block)
43
+ field_factory = FieldFactory::Join.new(name, type, options, &block)
44
+ @field_factories[field_factory.signature] = field_factory
45
+
46
+ if type.is_a?(Type::TextType)
47
+ @text_field_factories_cache[field_factory.name] = field_factory
48
+ else
49
+ @field_factories_cache[field_factory.name] = field_factory
50
+ end
51
+ end
52
+
41
53
  #
42
54
  # Add field_factories for fulltext search
43
55
  #
@@ -50,6 +62,7 @@ module Sunspot
50
62
  field_factory = FieldFactory::Static.new(name, Type::TextType.instance, options, &block)
51
63
  @text_field_factories[name] = field_factory
52
64
  @text_field_factories_cache[field_factory.name] = field_factory
65
+ @field_factories_cache[field_factory.name] = field_factory
53
66
  if stored
54
67
  @stored_field_factories_cache[field_factory.name] << field_factory
55
68
  end
@@ -70,6 +83,7 @@ module Sunspot
70
83
  field_factory = FieldFactory::Dynamic.new(name, type, options, &block)
71
84
  @dynamic_field_factories[field_factory.signature] = field_factory
72
85
  @dynamic_field_factories_cache[field_factory.name] = field_factory
86
+ @field_factories_cache[field_factory.name] = field_factory
73
87
  if stored
74
88
  @stored_field_factories_cache[field_factory.name] << field_factory
75
89
  end
@@ -96,6 +110,24 @@ module Sunspot
96
110
  end
97
111
  end
98
112
 
113
+ #
114
+ # Add id prefix for compositeId router
115
+ #
116
+ def add_id_prefix(attr_name, &block)
117
+ @id_prefix_extractor =
118
+ case attr_name
119
+ when Symbol
120
+ DataExtractor::AttributeExtractor.new(attr_name)
121
+ when String
122
+ DataExtractor::Constant.new(attr_name)
123
+ when nil
124
+ DataExtractor::BlockExtractor.new(&block) if block_given?
125
+ else
126
+ raise ArgumentError,
127
+ "The ID prefix has to be either a Symbol, a String or a Proc"
128
+ end
129
+ end
130
+
99
131
  #
100
132
  # Builder method for evaluating the setup DSL
101
133
  #
@@ -260,6 +292,16 @@ module Sunspot
260
292
  end
261
293
  end
262
294
 
295
+ def id_prefix_for(model)
296
+ if @id_prefix_extractor
297
+ value = @id_prefix_extractor.value_for(model)
298
+
299
+ if value.is_a?(String) and value.size > 0
300
+ value[-1] == "!" ? value : "#{value}!"
301
+ end
302
+ end
303
+ end
304
+
263
305
  protected
264
306
 
265
307
  #