ruben-sunspot 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. data/Gemfile +9 -0
  2. data/Gemfile.lock +22 -0
  3. data/History.txt +198 -0
  4. data/LICENSE +18 -0
  5. data/README.rdoc +244 -0
  6. data/Rakefile +11 -0
  7. data/TODO +13 -0
  8. data/VERSION.yml +4 -0
  9. data/bin/sunspot-installer +19 -0
  10. data/bin/sunspot-solr +74 -0
  11. data/installer/config/schema.yml +95 -0
  12. data/lib/light_config.rb +40 -0
  13. data/lib/sunspot.rb +529 -0
  14. data/lib/sunspot/adapters.rb +265 -0
  15. data/lib/sunspot/composite_setup.rb +202 -0
  16. data/lib/sunspot/configuration.rb +46 -0
  17. data/lib/sunspot/data_extractor.rb +50 -0
  18. data/lib/sunspot/dsl.rb +5 -0
  19. data/lib/sunspot/dsl/adjustable.rb +47 -0
  20. data/lib/sunspot/dsl/field_query.rb +266 -0
  21. data/lib/sunspot/dsl/fields.rb +113 -0
  22. data/lib/sunspot/dsl/fulltext.rb +243 -0
  23. data/lib/sunspot/dsl/function.rb +14 -0
  24. data/lib/sunspot/dsl/functional.rb +41 -0
  25. data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
  26. data/lib/sunspot/dsl/paginatable.rb +28 -0
  27. data/lib/sunspot/dsl/query_facet.rb +36 -0
  28. data/lib/sunspot/dsl/restriction.rb +25 -0
  29. data/lib/sunspot/dsl/scope.rb +229 -0
  30. data/lib/sunspot/dsl/search.rb +30 -0
  31. data/lib/sunspot/dsl/standard_query.rb +125 -0
  32. data/lib/sunspot/field.rb +192 -0
  33. data/lib/sunspot/field_factory.rb +147 -0
  34. data/lib/sunspot/indexer.rb +131 -0
  35. data/lib/sunspot/installer.rb +31 -0
  36. data/lib/sunspot/installer/library_installer.rb +45 -0
  37. data/lib/sunspot/installer/schema_builder.rb +219 -0
  38. data/lib/sunspot/installer/solrconfig_updater.rb +106 -0
  39. data/lib/sunspot/installer/task_helper.rb +18 -0
  40. data/lib/sunspot/query.rb +10 -0
  41. data/lib/sunspot/query/abstract_field_facet.rb +52 -0
  42. data/lib/sunspot/query/boost_query.rb +24 -0
  43. data/lib/sunspot/query/common_query.rb +85 -0
  44. data/lib/sunspot/query/composite_fulltext.rb +31 -0
  45. data/lib/sunspot/query/connective.rb +195 -0
  46. data/lib/sunspot/query/date_field_facet.rb +14 -0
  47. data/lib/sunspot/query/dismax.rb +126 -0
  48. data/lib/sunspot/query/field_facet.rb +41 -0
  49. data/lib/sunspot/query/filter.rb +38 -0
  50. data/lib/sunspot/query/function_query.rb +52 -0
  51. data/lib/sunspot/query/highlighting.rb +55 -0
  52. data/lib/sunspot/query/local.rb +26 -0
  53. data/lib/sunspot/query/more_like_this.rb +60 -0
  54. data/lib/sunspot/query/more_like_this_query.rb +12 -0
  55. data/lib/sunspot/query/pagination.rb +38 -0
  56. data/lib/sunspot/query/query_facet.rb +16 -0
  57. data/lib/sunspot/query/restriction.rb +265 -0
  58. data/lib/sunspot/query/scope.rb +16 -0
  59. data/lib/sunspot/query/sort.rb +95 -0
  60. data/lib/sunspot/query/sort_composite.rb +33 -0
  61. data/lib/sunspot/query/standard_query.rb +20 -0
  62. data/lib/sunspot/query/text_field_boost.rb +17 -0
  63. data/lib/sunspot/schema.rb +151 -0
  64. data/lib/sunspot/search.rb +9 -0
  65. data/lib/sunspot/search/abstract_search.rb +302 -0
  66. data/lib/sunspot/search/date_facet.rb +35 -0
  67. data/lib/sunspot/search/facet_row.rb +27 -0
  68. data/lib/sunspot/search/field_facet.rb +88 -0
  69. data/lib/sunspot/search/highlight.rb +38 -0
  70. data/lib/sunspot/search/hit.rb +136 -0
  71. data/lib/sunspot/search/more_like_this_search.rb +31 -0
  72. data/lib/sunspot/search/query_facet.rb +62 -0
  73. data/lib/sunspot/search/standard_search.rb +21 -0
  74. data/lib/sunspot/server.rb +152 -0
  75. data/lib/sunspot/session.rb +252 -0
  76. data/lib/sunspot/session_proxy.rb +71 -0
  77. data/lib/sunspot/session_proxy/abstract_session_proxy.rb +29 -0
  78. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +66 -0
  79. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +89 -0
  80. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +43 -0
  81. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +215 -0
  82. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +37 -0
  83. data/lib/sunspot/setup.rb +360 -0
  84. data/lib/sunspot/text_field_setup.rb +29 -0
  85. data/lib/sunspot/type.rb +342 -0
  86. data/lib/sunspot/util.rb +253 -0
  87. data/lib/sunspot/version.rb +3 -0
  88. data/solr/etc/jetty.xml +214 -0
  89. data/solr/etc/webdefault.xml +379 -0
  90. data/solr/lib/jetty-6.1.3.jar +0 -0
  91. data/solr/lib/jetty-util-6.1.3.jar +0 -0
  92. data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  93. data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
  94. data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
  95. data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  96. data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
  97. data/solr/solr/conf/admin-extra.html +31 -0
  98. data/solr/solr/conf/elevate.xml +36 -0
  99. data/solr/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
  100. data/solr/solr/conf/protwords.txt +21 -0
  101. data/solr/solr/conf/schema.xml +238 -0
  102. data/solr/solr/conf/scripts.conf +24 -0
  103. data/solr/solr/conf/solrconfig.xml +938 -0
  104. data/solr/solr/conf/spellings.txt +2 -0
  105. data/solr/solr/conf/stopwords.txt +58 -0
  106. data/solr/solr/conf/synonyms.txt +31 -0
  107. data/solr/solr/lib/lucene-spatial-2.9.1.jar +0 -0
  108. data/solr/solr/lib/solr-spatial-light-0.0.6.jar +0 -0
  109. data/solr/start.jar +0 -0
  110. data/solr/webapps/solr.war +0 -0
  111. data/spec/api/adapters_spec.rb +33 -0
  112. data/spec/api/binding_spec.rb +38 -0
  113. data/spec/api/indexer/attributes_spec.rb +149 -0
  114. data/spec/api/indexer/batch_spec.rb +46 -0
  115. data/spec/api/indexer/dynamic_fields_spec.rb +42 -0
  116. data/spec/api/indexer/fixed_fields_spec.rb +57 -0
  117. data/spec/api/indexer/fulltext_spec.rb +43 -0
  118. data/spec/api/indexer/removal_spec.rb +53 -0
  119. data/spec/api/indexer/spec_helper.rb +1 -0
  120. data/spec/api/indexer_spec.rb +14 -0
  121. data/spec/api/query/advanced_manipulation_examples.rb +35 -0
  122. data/spec/api/query/connectives_examples.rb +186 -0
  123. data/spec/api/query/dsl_spec.rb +18 -0
  124. data/spec/api/query/dynamic_fields_examples.rb +165 -0
  125. data/spec/api/query/faceting_examples.rb +399 -0
  126. data/spec/api/query/fulltext_examples.rb +315 -0
  127. data/spec/api/query/function_spec.rb +70 -0
  128. data/spec/api/query/highlighting_examples.rb +225 -0
  129. data/spec/api/query/local_examples.rb +38 -0
  130. data/spec/api/query/more_like_this_spec.rb +140 -0
  131. data/spec/api/query/ordering_pagination_examples.rb +97 -0
  132. data/spec/api/query/scope_examples.rb +263 -0
  133. data/spec/api/query/spec_helper.rb +1 -0
  134. data/spec/api/query/standard_spec.rb +28 -0
  135. data/spec/api/query/text_field_scoping_examples.rb +30 -0
  136. data/spec/api/query/types_spec.rb +20 -0
  137. data/spec/api/search/dynamic_fields_spec.rb +33 -0
  138. data/spec/api/search/faceting_spec.rb +356 -0
  139. data/spec/api/search/highlighting_spec.rb +69 -0
  140. data/spec/api/search/hits_spec.rb +149 -0
  141. data/spec/api/search/results_spec.rb +79 -0
  142. data/spec/api/search/search_spec.rb +23 -0
  143. data/spec/api/search/spec_helper.rb +1 -0
  144. data/spec/api/server_spec.rb +91 -0
  145. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +85 -0
  146. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +30 -0
  147. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +41 -0
  148. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +77 -0
  149. data/spec/api/session_proxy/spec_helper.rb +9 -0
  150. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +50 -0
  151. data/spec/api/session_spec.rb +198 -0
  152. data/spec/api/spec_helper.rb +3 -0
  153. data/spec/api/sunspot_spec.rb +18 -0
  154. data/spec/ext.rb +11 -0
  155. data/spec/helpers/indexer_helper.rb +29 -0
  156. data/spec/helpers/query_helper.rb +38 -0
  157. data/spec/helpers/search_helper.rb +80 -0
  158. data/spec/integration/dynamic_fields_spec.rb +55 -0
  159. data/spec/integration/faceting_spec.rb +238 -0
  160. data/spec/integration/highlighting_spec.rb +22 -0
  161. data/spec/integration/indexing_spec.rb +33 -0
  162. data/spec/integration/keyword_search_spec.rb +317 -0
  163. data/spec/integration/local_search_spec.rb +91 -0
  164. data/spec/integration/more_like_this_spec.rb +43 -0
  165. data/spec/integration/scoped_search_spec.rb +349 -0
  166. data/spec/integration/spec_helper.rb +7 -0
  167. data/spec/integration/stored_fields_spec.rb +10 -0
  168. data/spec/integration/test_pagination.rb +32 -0
  169. data/spec/mocks/adapters.rb +32 -0
  170. data/spec/mocks/blog.rb +3 -0
  171. data/spec/mocks/comment.rb +21 -0
  172. data/spec/mocks/connection.rb +126 -0
  173. data/spec/mocks/mock_adapter.rb +30 -0
  174. data/spec/mocks/mock_class_sharding_session_proxy.rb +24 -0
  175. data/spec/mocks/mock_record.rb +52 -0
  176. data/spec/mocks/mock_sharding_session_proxy.rb +15 -0
  177. data/spec/mocks/photo.rb +12 -0
  178. data/spec/mocks/post.rb +76 -0
  179. data/spec/mocks/super_class.rb +2 -0
  180. data/spec/mocks/user.rb +8 -0
  181. data/spec/spec_helper.rb +52 -0
  182. data/tasks/gemspec.rake +33 -0
  183. data/tasks/rcov.rake +28 -0
  184. data/tasks/rdoc.rake +27 -0
  185. data/tasks/schema.rake +19 -0
  186. data/tasks/spec.rake +24 -0
  187. data/tasks/todo.rake +4 -0
  188. metadata +356 -0
@@ -0,0 +1,243 @@
1
+ module Sunspot
2
+ module DSL
3
+ #
4
+ # This DSL exposes the functionality provided by Solr's fulltext Dismax
5
+ # handler.
6
+ #
7
+ class Fulltext
8
+ attr_reader :exclude_fields #:nodoc:
9
+
10
+ # accept function in boost
11
+ include Functional
12
+
13
+ def initialize(query, setup) #:nodoc:
14
+ @query, @setup = query, setup
15
+ @fields_added = false
16
+ @exclude_fields = []
17
+ end
18
+
19
+ #
20
+ # Specify which fields to search. Field names specified as arguments are
21
+ # given default boost; field boosts can be specified by passing a hash of
22
+ # field names keyed to boost values as the last argument.
23
+ #
24
+ # If you wish to boost certain fields without restricting which fields are
25
+ # searched, use #boost_fields
26
+ #
27
+ # === Example
28
+ #
29
+ # Sunspot.search(Post) do
30
+ # keywords 'search is cool' do
31
+ # fields(:body, :title => 2.0)
32
+ # end
33
+ # end
34
+ #
35
+ # This would search the :body field with default boost (1.0), and the :title
36
+ # field with a boost of 2.0
37
+ #
38
+ def fields(*field_names)
39
+ @fields_added = true
40
+ boosted_fields = field_names.pop if field_names.last.is_a?(Hash)
41
+ field_names.each do |field_name|
42
+ @setup.text_fields(field_name).each do |field|
43
+ @query.add_fulltext_field(field, field.default_boost)
44
+ end
45
+ end
46
+ if boosted_fields
47
+ boosted_fields.each_pair do |field_name, boost|
48
+ @setup.text_fields(field_name).each do |field|
49
+ @query.add_fulltext_field(field, boost)
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ #
56
+ # Exclude the given fields from the search. All fields that are configured
57
+ # for the types under search and not listed here will be searched.
58
+ #
59
+ def exclude_fields(*field_names)
60
+ @exclude_fields.concat(field_names)
61
+ end
62
+
63
+ #
64
+ # Enable keyword highlighting for this search. By default, the fields
65
+ # under search will be highlighted; you may also may pass one or more
66
+ # symbol arguments indicating fields to be highlighted (they don't even
67
+ # have to be the same fields you're searching).
68
+ #
69
+ # === Example
70
+ #
71
+ # Sunspot.search(Post) do
72
+ # keywords 'show me the highlighting' do
73
+ # highlight :title, :body
74
+ # end
75
+ # end
76
+ #
77
+ # You may also pass a hash of options as the last argument. Options are
78
+ # the following:
79
+ #
80
+ # Full disclosure: I barely understand what these options actually do;
81
+ # this documentation is pretty much just copied from the
82
+ # (http://wiki.apache.org/solr/HighlightingParameters#head-23ecd5061bc2c86a561f85dc1303979fe614b956)[Solr Wiki]
83
+ #
84
+ # :max_snippets::
85
+ # The maximum number of highlighted snippets to generate per field
86
+ # :fragment_size::
87
+ # The number of characters to consider for a highlighted fragment
88
+ # :merge_continuous_fragments::
89
+ # Collapse continuous fragments into a single fragment
90
+ # :phrase_highlighter::
91
+ # Highlight phrase terms only when they appear within the query phrase
92
+ # in the document
93
+ # :require_field_match::
94
+ # If true, a field will only be highlighted if the query matched in
95
+ # this particular field (only has an effect if :phrase_highlighter is
96
+ # true as well)
97
+ #
98
+ def highlight(*args)
99
+ options = args.last.kind_of?(Hash) ? args.pop : {}
100
+ fields = []
101
+ args.each { |field_name| fields.concat(@setup.text_fields(field_name)) }
102
+
103
+ @query.add_highlight(fields, options)
104
+ end
105
+
106
+ #
107
+ # Phrase fields are an awesome dismax feature that adds extra boost to
108
+ # documents for which all the fulltext keywords appear in close proximity
109
+ # in one of the given fields. Excellent for titles, headlines, etc.
110
+ #
111
+ # Boosted fields are specified in a hash of field names to a boost, as
112
+ # with the #fields and #boost_fields methods.
113
+ #
114
+ # === Example
115
+ #
116
+ # Sunspot.search(Post) do
117
+ # keywords 'nothing reveals like relevance' do
118
+ # phrase_fields :title => 2.0
119
+ # end
120
+ # end
121
+ #
122
+ def phrase_fields(boosted_fields)
123
+ if boosted_fields
124
+ boosted_fields.each_pair do |field_name, boost|
125
+ @setup.text_fields(field_name).each do |field|
126
+ @query.add_phrase_field(field, boost)
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ #
133
+ # The maximum number of words that can appear between search terms for a
134
+ # field to qualify for phrase field boost. See #query_phrase_slop for
135
+ # examples. Phrase slop is only meaningful if phrase fields are specified
136
+ # (see #phrase_fields), and it does not have an effect on which results
137
+ # are returned; only on what their respective boosts are.
138
+ #
139
+ def phrase_slop(slop)
140
+ @query.phrase_slop = slop
141
+ end
142
+
143
+ #
144
+ # Boost queries allow specification of an arbitrary scope for which
145
+ # matching documents should receive an extra boost. You can either specify
146
+ # a boost factor and a block, or a boost function. The block is evaluated
147
+ # in the usual scope DSL, and field names are attribute fields, not text
148
+ # fields, as in other scope.
149
+ #
150
+ # The boost function can be a constant (numeric or string literal),
151
+ # a field name or another function. You can build arbitrarily complex
152
+ # functions, which are passed transparently to solr.
153
+ #
154
+ # This method can be called more than once for different boost queries
155
+ # with different boosts.
156
+ #
157
+ # === Example
158
+ #
159
+ # Sunspot.search(Post) do
160
+ # keywords 'super fan' do
161
+ # boost(2.0) do
162
+ # with(:featured, true)
163
+ # end
164
+ #
165
+ # boost(function { sum(:average_rating, product(:popularity, 10)) })
166
+ # end
167
+ # end
168
+ #
169
+ # In the above search, featured posts will receive a boost of 2.0 and all posts
170
+ # will be boosted by (average_rating + popularity * 10).
171
+ #
172
+ def boost(factor_or_function, &block)
173
+ if factor_or_function.is_a?(Sunspot::Query::FunctionQuery)
174
+ @query.add_boost_function(factor_or_function)
175
+ else
176
+ Sunspot::Util.instance_eval_or_call(
177
+ Scope.new(@query.create_boost_query(factor_or_function), @setup),
178
+ &block
179
+ )
180
+ end
181
+ end
182
+
183
+ #
184
+ # Add boost to certain fields, without restricting which fields are
185
+ # searched.
186
+ #
187
+ # === Example
188
+ #
189
+ # Sunspot.search(Post) do
190
+ # keywords('pork sandwich') do
191
+ # boost_fields :title => 1.5
192
+ # end
193
+ # end
194
+ #
195
+ def boost_fields(boosts)
196
+ boosts.each_pair do |field_name, boost|
197
+ begin
198
+ @setup.text_fields(field_name).each do |field|
199
+ @query.add_fulltext_field(field, boost)
200
+ end
201
+ rescue Sunspot::UnrecognizedFieldError
202
+ # We'll let this one slide.
203
+ end
204
+ end
205
+ end
206
+
207
+ #
208
+ # The minimum number of search terms that a result must match. By
209
+ # default, all search terms must match; if the number of search terms
210
+ # is less than this number, the default behavior applies.
211
+ #
212
+ def minimum_match(minimum_match)
213
+ @query.minimum_match = minimum_match
214
+ end
215
+
216
+ #
217
+ # The number of words that can appear between the words in a
218
+ # user-entered phrase (i.e., keywords in quotes) and still match. For
219
+ # instance, in a search for "\"great pizza\"" with a query phrase slop of
220
+ # 1, "great pizza" and "great big pizza" will match, but "great monster of
221
+ # a pizza" will not. Default behavior is a query phrase slop of zero.
222
+ #
223
+ def query_phrase_slop(slop)
224
+ @query.query_phrase_slop = slop
225
+ end
226
+
227
+ #
228
+ # A tiebreaker coefficient for scores derived from subqueries that are
229
+ # lower-scoring than the maximum score subquery. Typically a near-zero
230
+ # value is useful. See
231
+ # http://wiki.apache.org/solr/DisMaxRequestHandler#tie_.28Tie_breaker.29
232
+ # for more information.
233
+ #
234
+ def tie(tie)
235
+ @query.tie = tie
236
+ end
237
+
238
+ def fields_added? #:nodoc:
239
+ @fields_added
240
+ end
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,14 @@
1
+ module Sunspot
2
+ module DSL
3
+ class Function #:nodoc:
4
+ def initialize(functional) #:nodoc:
5
+ @functional = functional
6
+ end
7
+
8
+ def method_missing(method, *args, &block)
9
+ function_args = args.map { |arg| @functional.create_function_query(arg) }
10
+ Sunspot::Query::FunctionalFunctionQuery.new(method, function_args)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,41 @@
1
+ module Sunspot
2
+ module DSL
3
+ #
4
+ # Mixin DSL to accept functions.
5
+ #
6
+ module Functional
7
+
8
+ #
9
+ # Specify a function query with a block that returns an expression.
10
+ #
11
+ # === Examples
12
+ #
13
+ # function { 10 }
14
+ # function { :average_rating }
15
+ # function { sum(:average_rating, 10) }
16
+ #
17
+ def function(&block)
18
+ expression = Sunspot::Util.instance_eval_or_call(
19
+ Function.new(self),
20
+ &block
21
+ )
22
+ create_function_query(expression)
23
+ end
24
+
25
+ #
26
+ # Creates an AbstractFunctionQuery from an expression, also called by
27
+ # Sunspot::DSL::Function
28
+ #
29
+ def create_function_query(expression) #:nodoc:
30
+ if expression.is_a?(Sunspot::Query::FunctionQuery)
31
+ expression
32
+ elsif expression.is_a?(Symbol)
33
+ Sunspot::Query::FieldFunctionQuery.new(@setup.field(expression))
34
+ else
35
+ Sunspot::Query::ConstantFunctionQuery.new(expression)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,56 @@
1
+ module Sunspot
2
+ module DSL #:nodoc:
3
+ #
4
+ # This class provides the DSL for MoreLikeThis queries.
5
+ #
6
+ class MoreLikeThisQuery < FieldQuery
7
+ include Paginatable, Adjustable
8
+
9
+ def fields(*field_names)
10
+ boosted_fields = field_names.pop if field_names.last.is_a?(Hash)
11
+ field_names.each do |name|
12
+ mlt_fields = @setup.more_like_this_fields(name)
13
+ raise(ArgumentError, "Field #{name} is not setup for more_like_this") if mlt_fields.empty?
14
+ mlt_fields.each { |field| @query.more_like_this.add_field(field) }
15
+ end
16
+ if boosted_fields
17
+ boosted_fields.each_pair do |field_name, boost|
18
+ @setup.more_like_this_fields(field_name).each do |field|
19
+ @query.more_like_this.add_field(field, boost)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def minimum_term_frequency(value)
26
+ @query.more_like_this.minimum_term_frequency = value
27
+ end
28
+ alias_method :mintf, :minimum_term_frequency
29
+
30
+ def minimum_document_frequency(value)
31
+ @query.more_like_this.minimum_document_frequency = value
32
+ end
33
+ alias_method :mindf, :minimum_document_frequency
34
+
35
+ def minimum_word_length(value)
36
+ @query.more_like_this.minimum_word_length = value
37
+ end
38
+ alias_method :minwl, :minimum_word_length
39
+
40
+ def maximum_word_length(value)
41
+ @query.more_like_this.maximum_word_length = value
42
+ end
43
+ alias_method :maxwl, :maximum_word_length
44
+
45
+ def maximum_query_terms(value)
46
+ @query.more_like_this.maximum_query_terms = value
47
+ end
48
+ alias_method :maxqt, :maximum_query_terms
49
+
50
+ def boost_by_relevance(should_boost)
51
+ @query.more_like_this.boost_by_relevance = should_boost
52
+ end
53
+ alias_method :boost, :boost_by_relevance
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,28 @@
1
+ module Sunspot
2
+ module DSL #:nodoc
3
+ module Paginatable
4
+ # Paginate your search. This works the same way as WillPaginate's
5
+ # paginate().
6
+ #
7
+ # Note that Solr searches are _always_ paginated. Not calling #paginate is
8
+ # the equivalent of calling:
9
+ #
10
+ # paginate(:page => 1, :per_page => Sunspot.config.pagination.default_per_page)
11
+ #
12
+ # ==== Options (options)
13
+ #
14
+ # :page<Integer,String>:: The requested page. The default is 1.
15
+ #
16
+ # :per_page<Integer,String>::
17
+ # How many results to return per page. The default is the value in
18
+ # +Sunspot.config.pagination.default_per_page+
19
+ #
20
+ def paginate(options = {})
21
+ page = options.delete(:page)
22
+ per_page = options.delete(:per_page)
23
+ raise ArgumentError, "unknown argument #{options.keys.first.inspect} passed to paginate" unless options.empty?
24
+ @query.paginate(page, per_page)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ module Sunspot
2
+ module DSL
3
+ #
4
+ # This tiny DSL class implements the DSL for the FieldQuery.facet
5
+ # method.
6
+ #
7
+ class QueryFacet
8
+ def initialize(query, setup, facet) #:nodoc:
9
+ @query, @setup, @facet = query, setup, facet
10
+ end
11
+
12
+ #
13
+ # Add a row to this query facet. The label argument can be anything; it's
14
+ # simply the value that's passed into the Sunspot::QueryFacetRow object
15
+ # corresponding to the row that's created. Use whatever seems most
16
+ # intuitive.
17
+ #
18
+ # The block is evaluated in the context of a Sunspot::DSL::Scope, meaning
19
+ # any restrictions can be placed on the documents matching this facet row.
20
+ #
21
+ # ==== Parameters
22
+ #
23
+ # label<Object>::
24
+ # An object used to identify this facet row in the results.
25
+ #
26
+ def row(label, &block)
27
+ query_facet = Sunspot::Query::QueryFacet.new
28
+ Sunspot::Util.instance_eval_or_call(
29
+ Scope.new(@query.add_query_facet(query_facet), @setup),
30
+ &block
31
+ )
32
+ @facet.add_row(label, query_facet.to_boolean_phrase)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ module Sunspot
2
+ module DSL
3
+ #
4
+ # This class presents an API for building restrictions in the query DSL. The
5
+ # methods exposed are the snake-cased names of the classes defined in the
6
+ # Sunspot::Restriction module, with the exception of Base. All
7
+ # methods take a single argument, which is the value to be applied to the
8
+ # restriction.
9
+ #
10
+ class Restriction
11
+ def initialize(field_name, query, negative) #:nodoc:
12
+ @field_name, @scope, @negative = field_name, query, negative
13
+ end
14
+
15
+ Sunspot::Query::Restriction.names.each do |class_name|
16
+ method_name = Util.snake_case(class_name.to_s)
17
+ module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
18
+ def #{method_name}(value)
19
+ @scope.add_restriction(@field_name, Sunspot::Query::Restriction::#{class_name}, value, @negative)
20
+ end
21
+ RUBY
22
+ end
23
+ end
24
+ end
25
+ end