gojee-sunspot 2.0.3 → 2.0.4

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 (178) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +5 -0
  3. data/History.txt +252 -0
  4. data/LICENSE +18 -0
  5. data/Rakefile +13 -0
  6. data/TODO +13 -0
  7. data/lib/light_config.rb +40 -0
  8. data/lib/sunspot/adapters.rb +265 -0
  9. data/lib/sunspot/batcher.rb +62 -0
  10. data/lib/sunspot/class_set.rb +23 -0
  11. data/lib/sunspot/composite_setup.rb +202 -0
  12. data/lib/sunspot/configuration.rb +53 -0
  13. data/lib/sunspot/data_extractor.rb +50 -0
  14. data/lib/sunspot/dsl/adjustable.rb +47 -0
  15. data/lib/sunspot/dsl/field_group.rb +57 -0
  16. data/lib/sunspot/dsl/field_query.rb +327 -0
  17. data/lib/sunspot/dsl/fields.rb +103 -0
  18. data/lib/sunspot/dsl/fulltext.rb +243 -0
  19. data/lib/sunspot/dsl/function.rb +27 -0
  20. data/lib/sunspot/dsl/functional.rb +44 -0
  21. data/lib/sunspot/dsl/more_like_this_query.rb +56 -0
  22. data/lib/sunspot/dsl/paginatable.rb +32 -0
  23. data/lib/sunspot/dsl/query_facet.rb +36 -0
  24. data/lib/sunspot/dsl/restriction.rb +25 -0
  25. data/lib/sunspot/dsl/restriction_with_near.rb +160 -0
  26. data/lib/sunspot/dsl/scope.rb +217 -0
  27. data/lib/sunspot/dsl/search.rb +30 -0
  28. data/lib/sunspot/dsl/standard_query.rb +123 -0
  29. data/lib/sunspot/dsl.rb +5 -0
  30. data/lib/sunspot/field.rb +193 -0
  31. data/lib/sunspot/field_factory.rb +129 -0
  32. data/lib/sunspot/indexer.rb +136 -0
  33. data/lib/sunspot/query/abstract_field_facet.rb +52 -0
  34. data/lib/sunspot/query/bbox.rb +15 -0
  35. data/lib/sunspot/query/boost_query.rb +24 -0
  36. data/lib/sunspot/query/common_query.rb +96 -0
  37. data/lib/sunspot/query/composite_fulltext.rb +36 -0
  38. data/lib/sunspot/query/connective.rb +206 -0
  39. data/lib/sunspot/query/date_field_facet.rb +14 -0
  40. data/lib/sunspot/query/dismax.rb +132 -0
  41. data/lib/sunspot/query/field_facet.rb +41 -0
  42. data/lib/sunspot/query/field_group.rb +36 -0
  43. data/lib/sunspot/query/filter.rb +38 -0
  44. data/lib/sunspot/query/function_query.rb +52 -0
  45. data/lib/sunspot/query/geo.rb +53 -0
  46. data/lib/sunspot/query/geofilt.rb +16 -0
  47. data/lib/sunspot/query/highlighting.rb +62 -0
  48. data/lib/sunspot/query/more_like_this.rb +61 -0
  49. data/lib/sunspot/query/more_like_this_query.rb +12 -0
  50. data/lib/sunspot/query/pagination.rb +42 -0
  51. data/lib/sunspot/query/query_facet.rb +16 -0
  52. data/lib/sunspot/query/restriction.rb +262 -0
  53. data/lib/sunspot/query/scope.rb +9 -0
  54. data/lib/sunspot/query/sort.rb +109 -0
  55. data/lib/sunspot/query/sort_composite.rb +34 -0
  56. data/lib/sunspot/query/standard_query.rb +16 -0
  57. data/lib/sunspot/query/text_field_boost.rb +17 -0
  58. data/lib/sunspot/query.rb +11 -0
  59. data/lib/sunspot/schema.rb +151 -0
  60. data/lib/sunspot/search/abstract_search.rb +281 -0
  61. data/lib/sunspot/search/date_facet.rb +35 -0
  62. data/lib/sunspot/search/facet_row.rb +27 -0
  63. data/lib/sunspot/search/field_facet.rb +88 -0
  64. data/lib/sunspot/search/field_group.rb +32 -0
  65. data/lib/sunspot/search/group.rb +50 -0
  66. data/lib/sunspot/search/highlight.rb +38 -0
  67. data/lib/sunspot/search/hit.rb +150 -0
  68. data/lib/sunspot/search/hit_enumerable.rb +72 -0
  69. data/lib/sunspot/search/more_like_this_search.rb +31 -0
  70. data/lib/sunspot/search/paginated_collection.rb +57 -0
  71. data/lib/sunspot/search/query_facet.rb +67 -0
  72. data/lib/sunspot/search/standard_search.rb +21 -0
  73. data/lib/sunspot/search.rb +9 -0
  74. data/lib/sunspot/session.rb +262 -0
  75. data/lib/sunspot/session_proxy/abstract_session_proxy.rb +29 -0
  76. data/lib/sunspot/session_proxy/class_sharding_session_proxy.rb +66 -0
  77. data/lib/sunspot/session_proxy/id_sharding_session_proxy.rb +89 -0
  78. data/lib/sunspot/session_proxy/master_slave_session_proxy.rb +43 -0
  79. data/lib/sunspot/session_proxy/multicore_session_proxy.rb +67 -0
  80. data/lib/sunspot/session_proxy/sharding_session_proxy.rb +222 -0
  81. data/lib/sunspot/session_proxy/silent_fail_session_proxy.rb +42 -0
  82. data/lib/sunspot/session_proxy/thread_local_session_proxy.rb +37 -0
  83. data/lib/sunspot/session_proxy.rb +95 -0
  84. data/lib/sunspot/setup.rb +350 -0
  85. data/lib/sunspot/text_field_setup.rb +29 -0
  86. data/lib/sunspot/type.rb +393 -0
  87. data/lib/sunspot/util.rb +252 -0
  88. data/lib/sunspot/version.rb +3 -0
  89. data/lib/sunspot.rb +579 -0
  90. data/log/.gitignore +1 -0
  91. data/pkg/.gitignore +1 -0
  92. data/script/console +10 -0
  93. data/spec/api/adapters_spec.rb +33 -0
  94. data/spec/api/batcher_spec.rb +112 -0
  95. data/spec/api/binding_spec.rb +50 -0
  96. data/spec/api/class_set_spec.rb +24 -0
  97. data/spec/api/hit_enumerable_spec.rb +47 -0
  98. data/spec/api/indexer/attributes_spec.rb +149 -0
  99. data/spec/api/indexer/batch_spec.rb +72 -0
  100. data/spec/api/indexer/dynamic_fields_spec.rb +42 -0
  101. data/spec/api/indexer/fixed_fields_spec.rb +57 -0
  102. data/spec/api/indexer/fulltext_spec.rb +43 -0
  103. data/spec/api/indexer/removal_spec.rb +53 -0
  104. data/spec/api/indexer/spec_helper.rb +1 -0
  105. data/spec/api/indexer_spec.rb +14 -0
  106. data/spec/api/query/advanced_manipulation_examples.rb +35 -0
  107. data/spec/api/query/connectives_examples.rb +189 -0
  108. data/spec/api/query/dsl_spec.rb +18 -0
  109. data/spec/api/query/dynamic_fields_examples.rb +165 -0
  110. data/spec/api/query/faceting_examples.rb +397 -0
  111. data/spec/api/query/fulltext_examples.rb +313 -0
  112. data/spec/api/query/function_spec.rb +79 -0
  113. data/spec/api/query/geo_examples.rb +68 -0
  114. data/spec/api/query/group_spec.rb +32 -0
  115. data/spec/api/query/highlighting_examples.rb +245 -0
  116. data/spec/api/query/more_like_this_spec.rb +140 -0
  117. data/spec/api/query/ordering_pagination_examples.rb +116 -0
  118. data/spec/api/query/scope_examples.rb +275 -0
  119. data/spec/api/query/spatial_examples.rb +27 -0
  120. data/spec/api/query/spec_helper.rb +1 -0
  121. data/spec/api/query/standard_spec.rb +29 -0
  122. data/spec/api/query/text_field_scoping_examples.rb +30 -0
  123. data/spec/api/query/types_spec.rb +20 -0
  124. data/spec/api/search/dynamic_fields_spec.rb +33 -0
  125. data/spec/api/search/faceting_spec.rb +360 -0
  126. data/spec/api/search/highlighting_spec.rb +69 -0
  127. data/spec/api/search/hits_spec.rb +131 -0
  128. data/spec/api/search/paginated_collection_spec.rb +36 -0
  129. data/spec/api/search/results_spec.rb +72 -0
  130. data/spec/api/search/search_spec.rb +23 -0
  131. data/spec/api/search/spec_helper.rb +1 -0
  132. data/spec/api/session_proxy/class_sharding_session_proxy_spec.rb +85 -0
  133. data/spec/api/session_proxy/id_sharding_session_proxy_spec.rb +30 -0
  134. data/spec/api/session_proxy/master_slave_session_proxy_spec.rb +41 -0
  135. data/spec/api/session_proxy/sharding_session_proxy_spec.rb +77 -0
  136. data/spec/api/session_proxy/silent_fail_session_proxy_spec.rb +24 -0
  137. data/spec/api/session_proxy/spec_helper.rb +9 -0
  138. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +39 -0
  139. data/spec/api/session_spec.rb +232 -0
  140. data/spec/api/spec_helper.rb +3 -0
  141. data/spec/api/sunspot_spec.rb +29 -0
  142. data/spec/ext.rb +11 -0
  143. data/spec/helpers/indexer_helper.rb +17 -0
  144. data/spec/helpers/integration_helper.rb +8 -0
  145. data/spec/helpers/mock_session_helper.rb +13 -0
  146. data/spec/helpers/query_helper.rb +26 -0
  147. data/spec/helpers/search_helper.rb +68 -0
  148. data/spec/integration/dynamic_fields_spec.rb +57 -0
  149. data/spec/integration/faceting_spec.rb +251 -0
  150. data/spec/integration/field_grouping_spec.rb +66 -0
  151. data/spec/integration/geospatial_spec.rb +85 -0
  152. data/spec/integration/highlighting_spec.rb +44 -0
  153. data/spec/integration/indexing_spec.rb +55 -0
  154. data/spec/integration/keyword_search_spec.rb +317 -0
  155. data/spec/integration/local_search_spec.rb +64 -0
  156. data/spec/integration/more_like_this_spec.rb +43 -0
  157. data/spec/integration/scoped_search_spec.rb +354 -0
  158. data/spec/integration/stored_fields_spec.rb +12 -0
  159. data/spec/integration/test_pagination.rb +43 -0
  160. data/spec/integration/unicode_spec.rb +15 -0
  161. data/spec/mocks/adapters.rb +32 -0
  162. data/spec/mocks/blog.rb +3 -0
  163. data/spec/mocks/comment.rb +21 -0
  164. data/spec/mocks/connection.rb +126 -0
  165. data/spec/mocks/mock_adapter.rb +30 -0
  166. data/spec/mocks/mock_class_sharding_session_proxy.rb +24 -0
  167. data/spec/mocks/mock_record.rb +52 -0
  168. data/spec/mocks/mock_sharding_session_proxy.rb +15 -0
  169. data/spec/mocks/photo.rb +11 -0
  170. data/spec/mocks/post.rb +86 -0
  171. data/spec/mocks/super_class.rb +2 -0
  172. data/spec/mocks/user.rb +13 -0
  173. data/spec/spec_helper.rb +40 -0
  174. data/sunspot.gemspec +42 -0
  175. data/tasks/rdoc.rake +27 -0
  176. data/tasks/schema.rake +19 -0
  177. data/tasks/todo.rake +4 -0
  178. metadata +261 -3
@@ -0,0 +1,23 @@
1
+ module Sunspot
2
+ class ClassSet
3
+ include Enumerable
4
+
5
+ def initialize
6
+ @name_to_klass = {}
7
+ end
8
+
9
+ def <<(klass)
10
+ @name_to_klass[klass.name.to_sym] = klass
11
+ self
12
+ end
13
+ alias_method :add, :<<
14
+
15
+ def each(&block)
16
+ @name_to_klass.values.each(&block)
17
+ end
18
+
19
+ def empty?
20
+ @name_to_klass.empty?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,202 @@
1
+ module Sunspot
2
+ #
3
+ # The CompositeSetup class encapsulates a collection of setups, and responds
4
+ # to a subset of the methods that Setup responds to (in particular, the
5
+ # methods required to build queries).
6
+ #
7
+ class CompositeSetup #:nodoc:
8
+ class << self
9
+ alias_method :for, :new
10
+ end
11
+
12
+ def initialize(types)
13
+ @types = types
14
+ end
15
+
16
+ #
17
+ # Collection of Setup objects for the enclosed types
18
+ #
19
+ # ==== Returns
20
+ #
21
+ # Array:: Collection of Setup objects
22
+ #
23
+ def setups
24
+ @setups ||= @types.map { |type| Setup.for(type) }
25
+ end
26
+
27
+ #
28
+ # Return the names of the encapsulated types
29
+ #
30
+ # ==== Returns
31
+ #
32
+ # Array:: Collection of class names
33
+ #
34
+ def type_names
35
+ @type_names ||= @types.map { |clazz| clazz.name }
36
+ end
37
+
38
+ #
39
+ # Get a text field object by its public name. A field will be returned if
40
+ # it is configured for any of the enclosed types.
41
+ #
42
+ # ==== Returns
43
+ #
44
+ # Sunspot::FulltextField:: Text field with the given public name
45
+ #
46
+ # ==== Raises
47
+ #
48
+ # UnrecognizedFieldError::
49
+ # If no field with that name is configured for any of the enclosed types.
50
+ #
51
+ def text_fields(field_name)
52
+ if text_fields = text_fields_hash[field_name.to_sym]
53
+ text_fields.to_a
54
+ else
55
+ raise(
56
+ UnrecognizedFieldError,
57
+ "No text field configured for #{@types * ', '} with name '#{field_name}'"
58
+ )
59
+ end
60
+ end
61
+
62
+ #
63
+ # Get a Sunspot::AttributeField instance corresponding to the given field name
64
+ #
65
+ # ==== Parameters
66
+ #
67
+ # field_name<Symbol>:: The public field name for which to find a field
68
+ #
69
+ # ==== Returns
70
+ #
71
+ # Sunspot::AttributeField The field object corresponding to the given name
72
+ #
73
+ # ==== Raises
74
+ #
75
+ # ArgumentError::
76
+ # If the given field name is not configured for the types being queried
77
+ #
78
+ def field(field_name) #:nodoc:
79
+ fields_hash[field_name.to_sym] || raise(
80
+ UnrecognizedFieldError,
81
+ "No field configured for #{@types * ', '} with name '#{field_name}'"
82
+ )
83
+ end
84
+
85
+ #
86
+ # Get a dynamic field factory for the given base name.
87
+ #
88
+ # ==== Returns
89
+ #
90
+ # DynamicFieldFactory:: Factory for dynamic fields with the given base name
91
+ #
92
+ # ==== Raises
93
+ #
94
+ # UnrecognizedFieldError::
95
+ # If the given base name is not configured as a dynamic field for the types being queried
96
+ #
97
+ def dynamic_field_factory(field_name)
98
+ dynamic_field_factories_hash[field_name.to_sym] || raise(
99
+ UnrecognizedFieldError,
100
+ "No dynamic field configured for #{@types * ', '} with name #{field_name.inspect}"
101
+ )
102
+ end
103
+
104
+ #
105
+ # Collection of all text fields configured for any of the enclosed types.
106
+ #
107
+ # === Returns
108
+ #
109
+ # Array:: Text fields configured for the enclosed types
110
+ #
111
+ def all_text_fields
112
+ @text_fields ||= text_fields_hash.values.map { |set| set.to_a }.flatten
113
+ end
114
+
115
+ def all_more_like_this_fields
116
+ @more_like_this_fields ||= more_like_this_fields_hash.values.map { |set| set.to_a }.flatten
117
+ end
118
+
119
+ private
120
+
121
+ #
122
+ # Return a hash of field names to text field objects, containing all fields
123
+ # that are configured for any of the types enclosed.
124
+ #
125
+ # ==== Returns
126
+ #
127
+ # Hash:: Hash of field names to text field objects.
128
+ #
129
+ def text_fields_hash
130
+ @text_fields_hash ||=
131
+ setups.inject({}) do |hash, setup|
132
+ setup.all_text_fields.each do |text_field|
133
+ (hash[text_field.name] ||= Set.new) << text_field
134
+ end
135
+ hash
136
+ end
137
+ end
138
+
139
+ def more_like_this_fields_hash
140
+ @more_like_this_fields_hash ||=
141
+ setups.inject({}) do |hash, setup|
142
+ setup.all_more_like_this_fields.each do |more_like_this_field|
143
+ (hash[more_like_this_field.name] ||= Set.new) << more_like_this_field
144
+ end
145
+ hash
146
+ end
147
+ end
148
+
149
+ #
150
+ # Return a hash of field names to field objects, containing all fields
151
+ # that are common to all of the classes enclosed. In order for fields
152
+ # to be common, they must be of the same type and have the same
153
+ # value for allow_multiple? and stored?. This method is memoized.
154
+ #
155
+ # ==== Returns
156
+ #
157
+ # Hash:: field names keyed to field objects
158
+ #
159
+ def fields_hash
160
+ @fields_hash ||=
161
+ begin
162
+ field_sets_hash = Hash.new { |h, k| h[k] = Set.new }
163
+ @types.each do |type|
164
+ Setup.for(type).fields.each do |field|
165
+ field_sets_hash[field.name.to_sym] << field
166
+ end
167
+ end
168
+ fields_hash = {}
169
+ field_sets_hash.each_pair do |field_name, set|
170
+ if set.length == 1
171
+ fields_hash[field_name] = set.to_a.first
172
+ end
173
+ end
174
+ fields_hash
175
+ end
176
+ end
177
+
178
+ #
179
+ # Return a hash of dynamic field base names to dynamic field factories for
180
+ # those base names. Criteria for the inclusion are the same as for
181
+ # #fields_hash()
182
+ #
183
+ def dynamic_field_factories_hash
184
+ @dynamic_field_factories_hash ||=
185
+ begin
186
+ dynamic_field_factories_hash = @types.inject({}) do |hash, type|
187
+ Setup.for(type).dynamic_field_factories.each do |field_factory|
188
+ (hash[field_factory.name.to_sym] ||= {})[type.name] = field_factory
189
+ end
190
+ hash
191
+ end
192
+ dynamic_field_factories_hash.each_pair do |field_name, field_configurations_hash|
193
+ if @types.any? { |type| field_configurations_hash[type.name].nil? }
194
+ dynamic_field_factories_hash.delete(field_name)
195
+ else
196
+ dynamic_field_factories_hash[field_name] = field_configurations_hash.values.first
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,53 @@
1
+ module Sunspot
2
+ # The Sunspot::Configuration module provides a factory method for Sunspot
3
+ # configuration objects. Available properties are:
4
+ #
5
+ # Sunspot.config.solr.url::
6
+ # The URL at which to connect to Solr
7
+ # (default: 'http://localhost:8983/solr')
8
+ # Sunspot.config.pagination.default_per_page::
9
+ # Solr always paginates its results. This sets Sunspot's default result
10
+ # count per page if it is not explicitly specified in the query.
11
+ # Sunspot.config.indexing.default_batch_size::
12
+ # This sets the batch size for indexing, default is 50
13
+ #
14
+ module Configuration
15
+ class <<self
16
+ # Factory method to build configuration instances.
17
+ #
18
+ # ==== Returns
19
+ #
20
+ # LightConfig::Configuration:: new configuration instance with defaults
21
+ #
22
+ def build #:nodoc:
23
+ LightConfig.build do
24
+ solr do
25
+ url 'http://127.0.0.1:8983/solr'
26
+ read_timeout nil
27
+ open_timeout nil
28
+ end
29
+ master_solr do
30
+ url nil
31
+ end
32
+ pagination do
33
+ default_per_page 30
34
+ end
35
+ indexing do
36
+ default_batch_size 50
37
+ end
38
+ end
39
+ end
40
+
41
+ # Location for the default solr configuration files,
42
+ # required for bootstrapping a new solr installation
43
+ #
44
+ # ==== Returns
45
+ #
46
+ # String:: Directory with default solr config files
47
+ #
48
+ def solr_default_configuration_location
49
+ File.join( File.dirname(__FILE__), '../../solr/solr/conf' )
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,50 @@
1
+ module Sunspot
2
+ #
3
+ # DataExtractors present an internal API for the indexer to use to extract
4
+ # field values from models for indexing. They must implement the #value_for
5
+ # method, which takes an object and returns the value extracted from it.
6
+ #
7
+ module DataExtractor #:nodoc: all
8
+ #
9
+ # AttributeExtractors extract data by simply calling a method on the block.
10
+ #
11
+ class AttributeExtractor
12
+ def initialize(attribute_name)
13
+ @attribute_name = attribute_name
14
+ end
15
+
16
+ def value_for(object)
17
+ object.send(@attribute_name)
18
+ end
19
+ end
20
+
21
+ #
22
+ # BlockExtractors extract data by evaluating a block in the context of the
23
+ # object instance, or if the block takes an argument, by passing the object
24
+ # as the argument to the block. Either way, the return value of the block is
25
+ # the value returned by the extractor.
26
+ #
27
+ class BlockExtractor
28
+ def initialize(&block)
29
+ @block = block
30
+ end
31
+
32
+ def value_for(object)
33
+ Util.instance_eval_or_call(object, &@block)
34
+ end
35
+ end
36
+
37
+ #
38
+ # Constant data extractors simply return the same value for every object.
39
+ #
40
+ class Constant
41
+ def initialize(value)
42
+ @value = value
43
+ end
44
+
45
+ def value_for(object)
46
+ @value
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,47 @@
1
+ module Sunspot
2
+ module DSL #:nodoc:
3
+ module Adjustable #:nodoc
4
+ # <strong>Expert:</strong> Adjust or reset the parameters passed to Solr.
5
+ # The adjustment will take place just before sending the params to solr,
6
+ # after Sunspot builds the Solr params based on the methods called in the
7
+ # DSL.
8
+ #
9
+ # Under normal circumstances, using this method should not be necessary;
10
+ # if you find that it is, please consider submitting a feature request.
11
+ # Using this method requires knowledge of Sunspot's internal Solr schema
12
+ # and Solr query representations, which are not part of Sunspot's public
13
+ # API; they could change at any time. <strong>This method is unsupported
14
+ # and your mileage may vary.</strong>
15
+ #
16
+ # ==== Examples
17
+ #
18
+ # Sunspot.search(Post) do
19
+ # adjust_solr_params do |params|
20
+ # params[:q] += ' AND something_s:more'
21
+ # end
22
+ # end
23
+ #
24
+ # Sunspot.more_like_this(my_post) do
25
+ # adjust_solr_params do |params|
26
+ # params["mlt.match.include"] = true
27
+ # end
28
+ # end
29
+ #
30
+ def adjust_solr_params( &block )
31
+ @query.solr_parameter_adjustment = block
32
+ end
33
+
34
+ #
35
+ # <strong>Expert:</strong> Use a custom request handler for this search.
36
+ # The general use case for this would be a request handler configuration
37
+ # you've defined in solrconfig that has different search components,
38
+ # defaults, etc. Using this to point at an entirely different type of
39
+ # request handler that Sunspot doesn't support probably won't get you very
40
+ # far.
41
+ #
42
+ def request_handler(request_handler)
43
+ @search.request_handler = request_handler
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,57 @@
1
+ module Sunspot
2
+ module DSL
3
+ class FieldGroup
4
+ def initialize(query, setup, group)
5
+ @query, @setup, @group = query, setup, group
6
+ end
7
+
8
+ #
9
+ # Sets the number of results (documents) to return for each group.
10
+ # Defaults to 1.
11
+ #
12
+ def limit(num)
13
+ @group.limit = num
14
+ end
15
+
16
+ #
17
+ # If set, facet counts are based on the most relevant document of
18
+ # each group matching the query.
19
+ #
20
+ # Supported in Solr 3.4 and above.
21
+ #
22
+ # ==== Example
23
+ #
24
+ # Sunspot.search(Post) do
25
+ # group :title do
26
+ # truncate
27
+ # end
28
+ #
29
+ # facet :title, :extra => :any
30
+ # end
31
+ #
32
+ def truncate
33
+ @group.truncate = true
34
+ end
35
+
36
+ # Specify the order that results should be returned in. This method can
37
+ # be called multiple times; precedence will be in the order given.
38
+ #
39
+ # ==== Parameters
40
+ #
41
+ # field_name<Symbol>:: the field to use for ordering
42
+ # direction<Symbol>:: :asc or :desc (default :asc)
43
+ #
44
+ def order_by(field_name, direction = nil)
45
+ sort =
46
+ if special = Sunspot::Query::Sort.special(field_name)
47
+ special.new(direction)
48
+ else
49
+ Sunspot::Query::Sort::FieldSort.new(
50
+ @setup.field(field_name), direction
51
+ )
52
+ end
53
+ @group.add_sort(sort)
54
+ end
55
+ end
56
+ end
57
+ end