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
@@ -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