sunspot 2.0.0 → 2.5.0

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.
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
@@ -1,6 +1,6 @@
1
1
  module Sunspot
2
2
  module DSL
3
- #
3
+ #
4
4
  # Provides an API for areas of the query DSL that operate on specific
5
5
  # fields. This functionality is provided by the query DSL and the dynamic
6
6
  # query DSL.
@@ -45,14 +45,14 @@ module Sunspot
45
45
  # the reference longitude
46
46
  # direction<Symbol>::
47
47
  # :asc or :desc (default :asc)
48
- #
48
+ #
49
49
  def order_by_geodist(field_name, lat, lon, direction = nil)
50
50
  @query.add_sort(
51
51
  Sunspot::Query::Sort::GeodistSort.new(@setup.field(field_name), lat, lon, direction)
52
52
  )
53
53
  end
54
54
 
55
- #
55
+ #
56
56
  # DEPRECATED Use <code>order_by(:random)</code>
57
57
  #
58
58
  def order_by_random
@@ -68,20 +68,22 @@ module Sunspot
68
68
  #
69
69
  # ==== Parameters
70
70
  #
71
- # field_name<Symbol>:: the field to use for grouping
71
+ # field_names...<Symbol>:: the fields to use for grouping
72
72
  def group(*field_names, &block)
73
+ group = Sunspot::Query::Group.new()
74
+
73
75
  field_names.each do |field_name|
74
76
  field = @setup.field(field_name)
75
- group = @query.add_group(Sunspot::Query::FieldGroup.new(field))
76
- @search.add_field_group(field)
77
+ group.add_field(field)
78
+ end
77
79
 
78
- if block
79
- Sunspot::Util.instance_eval_or_call(
80
- FieldGroup.new(@setup, group),
81
- &block
82
- )
83
- end
80
+ if block
81
+ dsl = Group.new(@setup, group)
82
+ Sunspot::Util.instance_eval_or_call(dsl, &block)
84
83
  end
84
+
85
+ @query.add_group(group)
86
+ @search.add_group(group)
85
87
  end
86
88
 
87
89
  #
@@ -109,7 +111,7 @@ module Sunspot
109
111
  # with(:blog_id, 1)
110
112
  # facet(:category_id)
111
113
  # end
112
- #
114
+ #
113
115
  # The facet specified above will have a row for each category_id that is
114
116
  # present in a document which also has a blog_id of 1.
115
117
  #
@@ -125,12 +127,12 @@ module Sunspot
125
127
  # category_filter = with(:category_id, 2)
126
128
  # facet(:category_id, :exclude => category_filter)
127
129
  # end
128
- #
130
+ #
129
131
  # Although the results of the above search will be restricted to those
130
132
  # with a category_id of 2, the category_id facet will operate as if a
131
133
  # category had not been selected, allowing the user to select additional
132
134
  # categories (which will presumably be ORed together).
133
- #
135
+ #
134
136
  # It possible to exclude multiple filters by passing an array:
135
137
  #
136
138
  # Sunspot.search(Post) do
@@ -141,7 +143,7 @@ module Sunspot
141
143
  # :exclude => [category_filter, author_filter].compact)
142
144
  # end
143
145
  #
144
- # You should consider using +.compact+ to ensure that the array does not
146
+ # You should consider using +.compact+ to ensure that the array does not
145
147
  # contain any nil values.
146
148
  #
147
149
  # <strong>As far as I can tell, Solr only supports multi-select with
@@ -331,6 +333,33 @@ module Sunspot
331
333
  end
332
334
  end
333
335
 
336
+ def json_facet(*field_names)
337
+ options = Sunspot::Util.extract_options_from(field_names)
338
+
339
+ field_names.each do |field_name|
340
+ field = @setup.field(field_name)
341
+ facet = Sunspot::Util.parse_json_facet(field_name, options, @setup)
342
+ @search.add_json_facet(field, options)
343
+ @query.add_query_facet(facet)
344
+ end
345
+ end
346
+
347
+ def stats(*field_names, &block)
348
+ options = Sunspot::Util.extract_options_from(field_names)
349
+
350
+ field_names.each do |field_name|
351
+ field = @setup.field(field_name)
352
+ query_stats = @query.add_stats(
353
+ Sunspot::Query::FieldStats.new(field, options)
354
+ )
355
+ search_stats = @search.add_field_stats(field)
356
+
357
+ Sunspot::Util.instance_eval_or_call(
358
+ FieldStats.new(query_stats, @setup, search_stats),
359
+ &block) if block
360
+ end
361
+ end
362
+
334
363
  def dynamic(base_name, &block)
335
364
  dynamic_field_factory = @setup.dynamic_field_factory(base_name)
336
365
  Sunspot::Util.instance_eval_or_call(
@@ -338,6 +367,30 @@ module Sunspot
338
367
  &block
339
368
  )
340
369
  end
370
+ #
371
+ # Specify that results should be ordered based on a
372
+ # FunctionQuery - http://wiki.apache.org/solr/FunctionQuery
373
+ # Solr 3.1 and up
374
+ #
375
+ # For example, to order by field1 + (field2*field3):
376
+ #
377
+ # order_by_function :sum, :field1, [:product, :field2, :field3], :desc
378
+ #
379
+ # ==== Parameters
380
+ # function_name<Symbol>::
381
+ # the function to run
382
+ # arguments::
383
+ # the arguments for this function.
384
+ # - Symbol for a field or function name
385
+ # - Array for a nested function
386
+ # - String for a literal constant
387
+ # direction<Symbol>::
388
+ # :asc or :desc
389
+ def order_by_function(*args)
390
+ @query.add_sort(
391
+ Sunspot::Query::Sort::FunctionSort.new(@setup,args)
392
+ )
393
+ end
341
394
  end
342
395
  end
343
396
  end
@@ -0,0 +1,25 @@
1
+ module Sunspot
2
+ module DSL
3
+ class FieldStats #:nodoc:
4
+ def initialize(query_stats, setup, search_stats) #:nodoc:
5
+ @query_stats, @setup, @search_stats = query_stats, setup, search_stats
6
+ end
7
+
8
+ def facet *field_names
9
+ field_names.each do |field_name|
10
+ field = @setup.field(field_name)
11
+
12
+ @query_stats.add_facet(field)
13
+ @search_stats.add_facet(field)
14
+ end
15
+ end
16
+
17
+ def json_facet(field_name, options = {})
18
+ field = @setup.field(field_name)
19
+ facet = Sunspot::Util.parse_json_facet(field_name, options, @setup)
20
+ @query_stats.add_json_facet(facet)
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -33,13 +33,10 @@ module Sunspot
33
33
  # DSL::Fulltext#boost_fields method.
34
34
  #
35
35
  def text(*names, &block)
36
- options = names.pop if names.last.is_a?(Hash)
36
+ options = names.last.is_a?(Hash) ? names.pop : {}
37
+
37
38
  names.each do |name|
38
- @setup.add_text_field_factory(
39
- name,
40
- options || {},
41
- &block
42
- )
39
+ @setup.add_text_field_factory(name, options, &block)
43
40
  end
44
41
  end
45
42
 
@@ -58,6 +55,22 @@ module Sunspot
58
55
  @setup.add_document_boost(attr_name, &block)
59
56
  end
60
57
 
58
+ #
59
+ # If you use the compositeId router for shards, you can send documents
60
+ # with a prefix in the document ID which will be used to calculate the
61
+ # hash Solr uses to determine the shard a document is sent to for indexing.
62
+ # The prefix can be anything you’d like it to be (it doesn’t have to be
63
+ # the shard name, for example), but it must be consistent so Solr
64
+ # behaves consistently.
65
+ #
66
+ # ==== Parameters
67
+ #
68
+ # attr_name<Symbol,String>:: Attribute name to call or a string constant
69
+ #
70
+ def id_prefix(attr_name = nil, &block)
71
+ @setup.add_id_prefix(attr_name, &block)
72
+ end
73
+
61
74
  # method_missing is used to provide access to typed fields, because
62
75
  # developers should be able to add new Sunspot::Type implementations
63
76
  # dynamically and have them recognized inside the Fields DSL. Like #text,
@@ -74,26 +87,33 @@ module Sunspot
74
87
  #
75
88
  def method_missing(method, *args, &block)
76
89
  options = Util.extract_options_from(args)
77
- type_const_name = "#{Util.camel_case(method.to_s.sub(/^dynamic_/, ''))}Type"
90
+ join = method.to_s == 'join'
91
+ type_string = join ? options.delete(:type).to_s : method.to_s
92
+ type_const_name = "#{Util.camel_case(type_string.sub(/^dynamic_/, ''))}Type"
78
93
  trie = options.delete(:trie)
79
94
  type_const_name = "Trie#{type_const_name}" if trie
95
+
80
96
  begin
81
97
  type_class = Type.const_get(type_const_name)
82
- rescue(NameError)
98
+ rescue NameError
83
99
  if trie
84
100
  raise ArgumentError, "Trie fields are only valid for numeric and time types"
85
101
  else
86
102
  super(method, *args, &block)
87
103
  end
88
104
  end
105
+
89
106
  type = type_class.instance
90
107
  name = args.shift
108
+
91
109
  if method.to_s =~ /^dynamic_/
92
110
  if type.accepts_dynamic?
93
111
  @setup.add_dynamic_field_factory(name, type, options, &block)
94
112
  else
95
113
  super(method, *args, &block)
96
114
  end
115
+ elsif join
116
+ @setup.add_join_field_factory(name, type, options.merge(:clazz => @setup.clazz), &block)
97
117
  else
98
118
  @setup.add_field_factory(name, type, options, &block)
99
119
  end
@@ -168,8 +168,12 @@ module Sunspot
168
168
  # will be boosted by (average_rating + popularity * 10).
169
169
  #
170
170
  def boost(factor_or_function, &block)
171
+ additive_boost(factor_or_function, &block)
172
+ end
173
+
174
+ def additive_boost(factor_or_function, &block)
171
175
  if factor_or_function.is_a?(Sunspot::Query::FunctionQuery)
172
- @query.add_boost_function(factor_or_function)
176
+ @query.add_additive_boost_function(factor_or_function)
173
177
  else
174
178
  Sunspot::Util.instance_eval_or_call(
175
179
  Scope.new(@query.create_boost_query(factor_or_function), @setup),
@@ -178,6 +182,10 @@ module Sunspot
178
182
  end
179
183
  end
180
184
 
185
+ def multiplicative_boost(factor_or_function)
186
+ @query.add_multiplicative_boost_function(factor_or_function)
187
+ end
188
+
181
189
  #
182
190
  # Add boost to certain fields, without restricting which fields are
183
191
  # searched.
@@ -0,0 +1,118 @@
1
+ module Sunspot
2
+ module DSL
3
+ class Group
4
+ def initialize(setup, group)
5
+ @setup, @group = setup, group
6
+ end
7
+
8
+ # Specify one or more fields for result grouping.
9
+ #
10
+ # ==== Parameters
11
+ #
12
+ # field_names...<Symbol>:: the fields to use for grouping
13
+ #
14
+ def field(*field_names, &block)
15
+ field_names.each do |field_name|
16
+ field = @setup.field(field_name)
17
+ @group.add_field(field)
18
+ end
19
+ end
20
+
21
+ # Specify a query to group results by.
22
+ #
23
+ # ==== Parameters
24
+ #
25
+ # label<Object>:: a label for this group; when #value is called on this
26
+ # group's results, this label will be returned.
27
+ #
28
+ def query(label, &block)
29
+ group_query = Sunspot::Query::GroupQuery.new(label)
30
+ Sunspot::Util.instance_eval_or_call(Scope.new(group_query, @setup), &block)
31
+ @group.add_query(group_query)
32
+ end
33
+
34
+ #
35
+ # Sets the number of results (documents) to return for each group.
36
+ # Defaults to 1.
37
+ #
38
+ def limit(num)
39
+ @group.limit = num
40
+ end
41
+
42
+ #
43
+ # If set, facet counts are based on the most relevant document of
44
+ # each group matching the query.
45
+ #
46
+ # Supported in Solr 3.4 and above.
47
+ #
48
+ # ==== Example
49
+ #
50
+ # Sunspot.search(Post) do
51
+ # group :title do
52
+ # truncate
53
+ # end
54
+ #
55
+ # facet :title, :extra => :any
56
+ # end
57
+ #
58
+ def truncate
59
+ @group.truncate = true
60
+ end
61
+
62
+ #
63
+ # The group.ngroups option true return the total number of groups
64
+ # this is expensive and sometimes you don't need it!
65
+ # If ngroups is false paginated_collection last_page? and total_pages wont't work.
66
+ # Defaults to true.
67
+ #
68
+ def ngroups(enabled)
69
+ @group.ngroups = enabled
70
+ end
71
+
72
+ # Specify the order that results should be returned in. This method can
73
+ # be called multiple times; precedence will be in the order given.
74
+ #
75
+ # ==== Parameters
76
+ #
77
+ # field_name<Symbol>:: the field to use for ordering
78
+ # direction<Symbol>:: :asc or :desc (default :asc)
79
+ #
80
+ def order_by(field_name, direction = nil)
81
+ sort =
82
+ if special = Sunspot::Query::Sort.special(field_name)
83
+ special.new(direction)
84
+ else
85
+ Sunspot::Query::Sort::FieldSort.new(
86
+ @setup.field(field_name), direction
87
+ )
88
+ end
89
+ @group.add_sort(sort)
90
+ end
91
+
92
+ #
93
+ # Specify that results should be ordered based on a
94
+ # FunctionQuery - http://wiki.apache.org/solr/FunctionQuery
95
+ # Solr 3.1 and up
96
+ #
97
+ # For example, to order by field1 + (field2*field3):
98
+ #
99
+ # order_by_function :sum, :field1, [:product, :field2, :field3], :desc
100
+ #
101
+ # ==== Parameters
102
+ # function_name<Symbol>::
103
+ # the function to run
104
+ # arguments::
105
+ # the arguments for this function.
106
+ # - Symbol for a field or function name
107
+ # - Array for a nested function
108
+ # - String for a literal constant
109
+ # direction<Symbol>::
110
+ # :asc or :desc
111
+ def order_by_function(*args)
112
+ @group.add_sort(
113
+ Sunspot::Query::Sort::FunctionSort.new(@setup,args)
114
+ )
115
+ end
116
+ end
117
+ end
118
+ end
@@ -20,12 +20,15 @@ module Sunspot
20
20
  # :offset<Integer,String>::
21
21
  # Applies a shift to paginated records. The default is 0.
22
22
  #
23
+ # :cursor<String>:: Cursor value for cursor-based pagination. The default is nil.
24
+ #
23
25
  def paginate(options = {})
24
26
  page = options.delete(:page)
25
27
  per_page = options.delete(:per_page)
26
28
  offset = options.delete(:offset)
29
+ cursor = options.delete(:cursor)
27
30
  raise ArgumentError, "unknown argument #{options.keys.first.inspect} passed to paginate" unless options.empty?
28
- @query.paginate(page, per_page, offset)
31
+ @query.paginate(page, per_page, offset, cursor)
29
32
  end
30
33
  end
31
34
  end
@@ -1,6 +1,6 @@
1
1
  module Sunspot
2
2
  module DSL #:nodoc:
3
- #
3
+ #
4
4
  # This DSL presents methods for constructing restrictions and other query
5
5
  # elements that are specific to fields. As well as being a superclass of
6
6
  # Sunspot::DSL::StandardQuery, which presents the main query block, this
@@ -12,7 +12,17 @@ module Sunspot
12
12
  @scope, @setup = scope, setup
13
13
  end
14
14
 
15
- #
15
+ # Build a restriction to return only fields of the type in the results.
16
+ def field_list(*args)
17
+ list = args.flatten.map { |field| @setup.field(field.to_sym).indexed_name.to_sym }
18
+ @query.add_field_list(Sunspot::Query::FieldList.new([:id] + list)) unless list.empty?
19
+ end
20
+
21
+ def without_stored_fields
22
+ @query.add_field_list(Sunspot::Query::FieldList.new([:id]))
23
+ end
24
+
25
+ #
16
26
  # Build a positive restriction. This method can take three forms: equality
17
27
  # restriction, restriction by another restriction, or identity
18
28
  # restriction.
@@ -62,7 +72,7 @@ module Sunspot
62
72
  # Sunspot.search do
63
73
  # with(:category_ids, [1, 5, 9])
64
74
  # end
65
- #
75
+ #
66
76
  # Other restriction types:
67
77
  #
68
78
  # Sunspot.search(Post) do
@@ -87,7 +97,7 @@ module Sunspot
87
97
  add_restriction(true, *args)
88
98
  end
89
99
 
90
- #
100
+ #
91
101
  # Create a disjunction, scoping the results to documents that match any
92
102
  # of the enclosed restrictions.
93
103
  #
@@ -109,7 +119,7 @@ module Sunspot
109
119
  disjunction
110
120
  end
111
121
 
112
- #
122
+ #
113
123
  # Create a conjunction, scoping the results to documents that match all of
114
124
  # the enclosed restrictions. When called from the top level of a search
115
125
  # block, this has no effect, but can be useful for grouping a conjunction
@@ -138,9 +148,9 @@ module Sunspot
138
148
  # The block API is implemented by Sunspot::DSL::FieldQuery, which is a
139
149
  # superclass of the Query DSL (thus providing a subset of the API, in
140
150
  # particular only methods that refer to particular fields).
141
- #
151
+ #
142
152
  # ==== Parameters
143
- #
153
+ #
144
154
  # base_name<Symbol>:: The base name for the dynamic field definition
145
155
  #
146
156
  # ==== Example
@@ -160,14 +170,14 @@ module Sunspot
160
170
  )
161
171
  end
162
172
 
163
- #
173
+ #
164
174
  # Apply scope-type restrictions on fulltext fields. In certain situations,
165
175
  # it may be desirable to place logical restrictions on text fields.
166
176
  # Remember that text fields are tokenized; your mileage may very.
167
177
  #
168
178
  # The block works exactly like a normal scope, except that the field names
169
179
  # refer to text fields instead of attribute fields.
170
- #
180
+ #
171
181
  # === Example
172
182
  #
173
183
  # Sunspot.search(Post) do
@@ -208,7 +218,6 @@ module Sunspot
208
218
  )
209
219
  end
210
220
  end
211
-
212
221
  end
213
222
  end
214
223
  end