erichummel-sunspot 1.2.1 → 2.0.0.pre.111215

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/.gitignore +0 -1
  2. data/Gemfile +2 -1
  3. data/History.txt +30 -0
  4. data/Rakefile +5 -9
  5. data/lib/sunspot.rb +13 -3
  6. data/lib/sunspot/batcher.rb +62 -0
  7. data/lib/sunspot/class_set.rb +23 -0
  8. data/lib/sunspot/configuration.rb +7 -0
  9. data/lib/sunspot/dsl.rb +1 -1
  10. data/lib/sunspot/dsl/field_group.rb +57 -0
  11. data/lib/sunspot/dsl/field_query.rb +48 -0
  12. data/lib/sunspot/dsl/function.rb +13 -0
  13. data/lib/sunspot/dsl/paginatable.rb +5 -1
  14. data/lib/sunspot/dsl/restriction_with_near.rb +39 -0
  15. data/lib/sunspot/dsl/scope.rb +4 -4
  16. data/lib/sunspot/dsl/search.rb +2 -2
  17. data/lib/sunspot/dsl/standard_query.rb +2 -0
  18. data/lib/sunspot/indexer.rb +12 -7
  19. data/lib/sunspot/query.rb +3 -3
  20. data/lib/sunspot/query/bbox.rb +15 -0
  21. data/lib/sunspot/query/common_query.rb +13 -2
  22. data/lib/sunspot/query/dismax.rb +5 -1
  23. data/lib/sunspot/query/field_group.rb +36 -0
  24. data/lib/sunspot/query/geofilt.rb +16 -0
  25. data/lib/sunspot/query/highlighting.rb +8 -1
  26. data/lib/sunspot/query/pagination.rb +8 -4
  27. data/lib/sunspot/query/sort.rb +14 -0
  28. data/lib/sunspot/query/sort_composite.rb +3 -2
  29. data/lib/sunspot/search.rb +1 -1
  30. data/lib/sunspot/search/abstract_search.rb +53 -65
  31. data/lib/sunspot/search/field_group.rb +32 -0
  32. data/lib/sunspot/search/group.rb +50 -0
  33. data/lib/sunspot/search/hit.rb +21 -7
  34. data/lib/sunspot/search/hit_enumerable.rb +72 -0
  35. data/lib/sunspot/search/paginated_collection.rb +5 -3
  36. data/lib/sunspot/session.rb +3 -1
  37. data/lib/sunspot/type.rb +21 -0
  38. data/lib/sunspot/util.rb +9 -0
  39. data/lib/sunspot/version.rb +1 -1
  40. data/spec/api/batcher_spec.rb +112 -0
  41. data/spec/api/class_set_spec.rb +24 -0
  42. data/spec/api/hit_enumerable_spec.rb +47 -0
  43. data/spec/api/indexer/batch_spec.rb +29 -3
  44. data/spec/api/query/function_spec.rb +9 -0
  45. data/spec/api/query/group_spec.rb +32 -0
  46. data/spec/api/query/highlighting_examples.rb +22 -0
  47. data/spec/api/query/ordering_pagination_examples.rb +21 -0
  48. data/spec/api/query/spatial_examples.rb +27 -0
  49. data/spec/api/query/standard_spec.rb +1 -0
  50. data/spec/api/search/hits_spec.rb +11 -0
  51. data/spec/api/search/paginated_collection_spec.rb +10 -0
  52. data/spec/api/search/results_spec.rb +6 -0
  53. data/spec/api/session_proxy/thread_local_session_proxy_spec.rb +0 -11
  54. data/spec/api/session_spec.rb +12 -0
  55. data/spec/api/sunspot_spec.rb +11 -0
  56. data/spec/helpers/indexer_helper.rb +0 -12
  57. data/spec/helpers/integration_helper.rb +8 -0
  58. data/spec/helpers/mock_session_helper.rb +13 -0
  59. data/spec/helpers/query_helper.rb +0 -12
  60. data/spec/helpers/search_helper.rb +0 -12
  61. data/spec/integration/dynamic_fields_spec.rb +2 -0
  62. data/spec/integration/faceting_spec.rb +14 -1
  63. data/spec/integration/field_grouping_spec.rb +66 -0
  64. data/spec/integration/geospatial_spec.rb +85 -0
  65. data/spec/integration/highlighting_spec.rb +22 -0
  66. data/spec/integration/indexing_spec.rb +23 -1
  67. data/spec/integration/keyword_search_spec.rb +1 -1
  68. data/spec/integration/local_search_spec.rb +1 -1
  69. data/spec/integration/more_like_this_spec.rb +1 -1
  70. data/spec/integration/scoped_search_spec.rb +1 -1
  71. data/spec/integration/stored_fields_spec.rb +2 -0
  72. data/spec/integration/test_pagination.rb +13 -2
  73. data/spec/integration/unicode_spec.rb +15 -0
  74. data/spec/mocks/connection.rb +4 -4
  75. data/spec/mocks/post.rb +1 -0
  76. data/spec/spec_helper.rb +21 -11
  77. data/sunspot.gemspec +42 -0
  78. data/tasks/rdoc.rake +2 -2
  79. metadata +95 -135
  80. data/VERSION.yml +0 -4
  81. data/bin/sunspot-installer +0 -19
  82. data/bin/sunspot-solr +0 -74
  83. data/installer/config/schema.yml +0 -95
  84. data/lib/sunspot/installer.rb +0 -31
  85. data/lib/sunspot/installer/library_installer.rb +0 -45
  86. data/lib/sunspot/installer/schema_builder.rb +0 -219
  87. data/lib/sunspot/installer/solrconfig_updater.rb +0 -76
  88. data/lib/sunspot/installer/task_helper.rb +0 -18
  89. data/lib/sunspot/server.rb +0 -152
  90. data/solr-1.3/etc/jetty.xml +0 -212
  91. data/solr-1.3/etc/webdefault.xml +0 -379
  92. data/solr-1.3/lib/jetty-6.1.3.jar +0 -0
  93. data/solr-1.3/lib/jetty-util-6.1.3.jar +0 -0
  94. data/solr-1.3/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  95. data/solr-1.3/lib/jsp-2.1/core-3.1.1.jar +0 -0
  96. data/solr-1.3/lib/jsp-2.1/jsp-2.1.jar +0 -0
  97. data/solr-1.3/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  98. data/solr-1.3/lib/servlet-api-2.5-6.1.3.jar +0 -0
  99. data/solr-1.3/solr/conf/elevate.xml +0 -36
  100. data/solr-1.3/solr/conf/protwords.txt +0 -21
  101. data/solr-1.3/solr/conf/schema.xml +0 -64
  102. data/solr-1.3/solr/conf/solrconfig.xml +0 -725
  103. data/solr-1.3/solr/conf/stopwords.txt +0 -57
  104. data/solr-1.3/solr/conf/synonyms.txt +0 -31
  105. data/solr-1.3/solr/lib/geoapi-nogenerics-2.1-M2.jar +0 -0
  106. data/solr-1.3/solr/lib/gt2-referencing-2.3.1.jar +0 -0
  107. data/solr-1.3/solr/lib/jsr108-0.01.jar +0 -0
  108. data/solr-1.3/solr/lib/locallucene.jar +0 -0
  109. data/solr-1.3/solr/lib/localsolr.jar +0 -0
  110. data/solr-1.3/start.jar +0 -0
  111. data/solr-1.3/webapps/solr.war +0 -0
  112. data/solr/README.txt +0 -42
  113. data/solr/etc/jetty.xml +0 -218
  114. data/solr/etc/webdefault.xml +0 -379
  115. data/solr/lib/jetty-6.1.3.jar +0 -0
  116. data/solr/lib/jetty-util-6.1.3.jar +0 -0
  117. data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
  118. data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
  119. data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
  120. data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
  121. data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
  122. data/solr/solr/.gitignore +0 -1
  123. data/solr/solr/README.txt +0 -54
  124. data/solr/solr/conf/admin-extra.html +0 -31
  125. data/solr/solr/conf/elevate.xml +0 -36
  126. data/solr/solr/conf/mapping-ISOLatin1Accent.txt +0 -246
  127. data/solr/solr/conf/protwords.txt +0 -21
  128. data/solr/solr/conf/schema.xml +0 -238
  129. data/solr/solr/conf/scripts.conf +0 -24
  130. data/solr/solr/conf/solrconfig.xml +0 -934
  131. data/solr/solr/conf/spellings.txt +0 -2
  132. data/solr/solr/conf/stopwords.txt +0 -58
  133. data/solr/solr/conf/synonyms.txt +0 -31
  134. data/solr/solr/conf/xslt/example.xsl +0 -132
  135. data/solr/solr/conf/xslt/example_atom.xsl +0 -67
  136. data/solr/solr/conf/xslt/example_rss.xsl +0 -66
  137. data/solr/solr/conf/xslt/luke.xsl +0 -337
  138. data/solr/start.jar +0 -0
  139. data/solr/webapps/solr.war +0 -0
  140. data/spec/api/server_spec.rb +0 -91
  141. data/spec/integration/spec_helper.rb +0 -7
@@ -3,9 +3,9 @@ module Sunspot
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
- # Sunspot::DSL::Query, which presents the main query block, this DSL class
7
- # is also used directly inside the #dynamic() block, which only allows
8
- # operations on specific fields.
6
+ # Sunspot::DSL::StandardQuery, which presents the main query block, this
7
+ # DSL class is also used directly inside the #dynamic() block, which only
8
+ # allows operations on specific fields.
9
9
  #
10
10
  class Scope
11
11
  NONE = Object.new
@@ -41,7 +41,7 @@ module Sunspot
41
41
  #
42
42
  # ==== Returns
43
43
  #
44
- # Sunspot::DSL::Query::Restriction::
44
+ # Sunspot::DSL::Restriction::
45
45
  # Restriction DSL object (if only one argument is passed which is a
46
46
  # field name)
47
47
  #
@@ -2,8 +2,8 @@ module Sunspot
2
2
  module DSL
3
3
  #
4
4
  # This top-level DSL class is the context in which the block passed to
5
- # Sunspot.query. See Sunspot::DSL::Query, Sunspot::DSL::FieldQuery, and
6
- # Sunspot::DSL::Scope for the full API presented.
5
+ # Sunspot.query. See Sunspot::DSL::StandardQuery, Sunspot::DSL::FieldQuery,
6
+ # and Sunspot::DSL::Scope for the full API presented.
7
7
  #
8
8
  class Search < StandardQuery
9
9
  def initialize(search, setup) #:nodoc:
@@ -35,6 +35,8 @@ module Sunspot
35
35
  # :highlight<Boolean,Array>::
36
36
  # If true, perform keyword highlighting on all searched fields. If an
37
37
  # array of field names, perform highlighting on the specified fields.
38
+ # Note that for highlighting to work, the desired fields have to be set
39
+ # up with :stored => true.
38
40
  # This can also be called from within the fulltext block.
39
41
  # :minimum_match<Integer>::
40
42
  # The minimum number of search terms that a result must match. By
@@ -1,3 +1,5 @@
1
+ require 'sunspot/batcher'
2
+
1
3
  module Sunspot
2
4
  #
3
5
  # This class presents a service for adding, updating, and removing data
@@ -22,10 +24,10 @@ module Sunspot
22
24
  #
23
25
  def add(model)
24
26
  documents = Util.Array(model).map { |m| prepare(m) }
25
- if @batch.nil?
26
- add_documents(documents)
27
+ if batcher.batching?
28
+ batcher.concat(documents)
27
29
  else
28
- @batch.concat(documents)
30
+ add_documents(documents)
29
31
  end
30
32
  end
31
33
 
@@ -69,19 +71,22 @@ module Sunspot
69
71
  # Start batch processing
70
72
  #
71
73
  def start_batch
72
- @batch = []
74
+ batcher.start_new
73
75
  end
74
76
 
75
77
  #
76
78
  # Write batch out to Solr and clear it
77
79
  #
78
80
  def flush_batch
79
- add_documents(@batch)
80
- @batch = nil
81
+ add_documents(batcher.end_current)
81
82
  end
82
83
 
83
84
  private
84
85
 
86
+ def batcher
87
+ @batcher ||= Batcher.new
88
+ end
89
+
85
90
  #
86
91
  # Convert documents into hash of indexed properties
87
92
  #
@@ -107,7 +112,7 @@ module Sunspot
107
112
  # pairs.
108
113
  #
109
114
  def document_for(model)
110
- RSolr::Message::Document.new(
115
+ RSolr::Xml::Document.new(
111
116
  :id => Adapters::InstanceAdapter.adapt(model).index_id,
112
117
  :type => Util.superclasses_for(model.class).map { |clazz| clazz.name }
113
118
  )
@@ -1,8 +1,8 @@
1
1
  %w(filter abstract_field_facet connective boost_query date_field_facet dismax
2
2
  field_facet highlighting pagination restriction common_query
3
- standard_query more_like_this more_like_this_query geo query_facet scope
4
- sort sort_composite text_field_boost function_query
5
- composite_fulltext).each do |file|
3
+ standard_query more_like_this more_like_this_query geo geofilt bbox query_facet
4
+ scope sort sort_composite text_field_boost function_query
5
+ composite_fulltext field_group).each do |file|
6
6
  require(File.join(File.dirname(__FILE__), 'query', file))
7
7
  end
8
8
  module Sunspot
@@ -0,0 +1,15 @@
1
+ module Sunspot
2
+ module Query
3
+ class Bbox
4
+ def initialize(field, first_corner, second_corner)
5
+ @field, @first_corner, @second_corner = field, first_corner, second_corner
6
+ end
7
+
8
+ def to_params
9
+ filter = "#{@field.indexed_name}:[#{@first_corner.join(",")} TO #{@second_corner.join(",")}]"
10
+
11
+ {:fq => filter}
12
+ end
13
+ end
14
+ end
15
+ end
@@ -20,6 +20,11 @@ module Sunspot
20
20
  @sort << sort
21
21
  end
22
22
 
23
+ def add_group(group)
24
+ @components << group
25
+ group
26
+ end
27
+
23
28
  def add_field_facet(facet)
24
29
  @components << facet
25
30
  facet
@@ -35,12 +40,18 @@ module Sunspot
35
40
  function
36
41
  end
37
42
 
38
- def paginate(page, per_page)
43
+ def add_geo(geo)
44
+ @components << geo
45
+ geo
46
+ end
47
+
48
+ def paginate(page, per_page, offset = nil)
39
49
  if @pagination
50
+ @pagination.offset = offset
40
51
  @pagination.page = page
41
52
  @pagination.per_page = per_page
42
53
  else
43
- @components << @pagination = Pagination.new(page, per_page)
54
+ @components << @pagination = Pagination.new(page, per_page, offset)
44
55
  end
45
56
  end
46
57
 
@@ -64,7 +64,7 @@ module Sunspot
64
64
  params.delete :defType
65
65
  params.delete :fl
66
66
  keywords = params.delete(:q)
67
- options = params.map { |key, value| "#{key}='#{escape_quotes(value)}'"}.join(' ')
67
+ options = params.map { |key, value| escape_param(key, value) }.join(' ')
68
68
  "_query_:\"{!dismax #{options}}#{escape_quotes(keywords)}\""
69
69
  end
70
70
 
@@ -117,6 +117,10 @@ module Sunspot
117
117
 
118
118
 
119
119
  private
120
+
121
+ def escape_param(key, value)
122
+ "#{key}='#{escape_quotes(Array(value).join(" "))}'"
123
+ end
120
124
 
121
125
  def escape_quotes(value)
122
126
  return value unless value.is_a? String
@@ -0,0 +1,36 @@
1
+ module Sunspot
2
+ module Query
3
+ #
4
+ # A FieldGroup groups by the unique values of a given field.
5
+ #
6
+ class FieldGroup
7
+ attr_accessor :limit, :truncate
8
+
9
+ def initialize(field)
10
+ if field.multiple?
11
+ raise(ArgumentError, "#{field.name} cannot be used for grouping because it is a multiple-value field")
12
+ end
13
+ @field = field
14
+
15
+ @sort = SortComposite.new
16
+ end
17
+
18
+ def add_sort(sort)
19
+ @sort << sort
20
+ end
21
+
22
+ def to_params
23
+ params = {
24
+ :group => "true",
25
+ :"group.field" => @field.indexed_name,
26
+ }
27
+
28
+ params.merge!(@sort.to_params("group."))
29
+ params[:"group.limit"] = @limit if @limit
30
+ params[:"group.truncate"] = @truncate if @truncate
31
+
32
+ params
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ module Sunspot
2
+ module Query
3
+ class Geofilt
4
+ def initialize(field, lat, lon, radius, options = {})
5
+ @field, @lat, @lon, @radius, @options = field, lat, lon, radius, options
6
+ end
7
+
8
+ def to_params
9
+ func = @options[:bbox] ? "bbox" : "geofilt"
10
+
11
+ filter = "{!#{func} sfield=#{@field.indexed_name} pt=#{@lat},#{@lon} d=#{@radius}}"
12
+ {:fq => filter}
13
+ end
14
+ end
15
+ end
16
+ end
@@ -9,7 +9,7 @@ module Sunspot
9
9
  @options = options
10
10
  end
11
11
 
12
- #
12
+ #
13
13
  # Return Solr highlighting params
14
14
  #
15
15
  def to_params
@@ -36,6 +36,13 @@ module Sunspot
36
36
  params.merge!(make_params('requireFieldMatch', 'true'))
37
37
  end
38
38
  end
39
+ if formatter = @options[:formatter]
40
+ params.merge!(make_params('formatter', formatter))
41
+ end
42
+ if fragmenter = @options[:fragmenter]
43
+ params.merge!(make_params('fragmenter', fragmenter))
44
+ end
45
+
39
46
  params
40
47
  end
41
48
 
@@ -6,10 +6,10 @@ module Sunspot
6
6
  # reference to it and updates it if pagination is changed.
7
7
  #
8
8
  class Pagination #:nodoc:
9
- attr_reader :page, :per_page
9
+ attr_reader :page, :per_page, :offset
10
10
 
11
- def initialize(page = nil, per_page = nil)
12
- self.page, self.per_page = page, per_page
11
+ def initialize(page = nil, per_page = nil, offset = nil)
12
+ self.offset, self.page, self.per_page = offset, page, per_page
13
13
  end
14
14
 
15
15
  def to_params
@@ -24,10 +24,14 @@ module Sunspot
24
24
  @per_page = per_page.to_i if per_page
25
25
  end
26
26
 
27
+ def offset=(offset)
28
+ @offset = offset.to_i
29
+ end
30
+
27
31
  private
28
32
 
29
33
  def start
30
- (@page - 1) * @per_page
34
+ (@page - 1) * @per_page + @offset
31
35
  end
32
36
 
33
37
  def rows
@@ -90,6 +90,20 @@ module Sunspot
90
90
  "score #{direction_for_solr}"
91
91
  end
92
92
  end
93
+
94
+ #
95
+ # A GeodistSort sorts by distance from a given point.
96
+ #
97
+ class GeodistSort < FieldSort
98
+ def initialize(field, lat, lon, direction)
99
+ @lat, @lon = lat, lon
100
+ super(field, direction)
101
+ end
102
+
103
+ def to_param
104
+ "geodist(#{@field.indexed_name.to_sym},#{@lat},#{@lon}) #{direction_for_solr}"
105
+ end
106
+ end
93
107
  end
94
108
  end
95
109
  end
@@ -21,9 +21,10 @@ module Sunspot
21
21
  #
22
22
  # Combine the sorts into a single param by joining them
23
23
  #
24
- def to_params
24
+ def to_params(prefix = "")
25
25
  unless @sorts.empty?
26
- { :sort => @sorts.map { |sort| sort.to_param } * ', ' }
26
+ key = "#{prefix}sort".to_sym
27
+ { key => @sorts.map { |sort| sort.to_param } * ', ' }
27
28
  else
28
29
  {}
29
30
  end
@@ -1,5 +1,5 @@
1
1
  %w(abstract_search standard_search more_like_this_search query_facet field_facet
2
- date_facet facet_row hit highlight).each do |file|
2
+ date_facet facet_row hit highlight field_group group hit_enumerable).each do |file|
3
3
  require File.join(File.dirname(__FILE__), 'search', file)
4
4
  end
5
5
 
@@ -1,4 +1,5 @@
1
1
  require 'sunspot/search/paginated_collection'
2
+ require 'sunspot/search/hit_enumerable'
2
3
 
3
4
  module Sunspot
4
5
  module Search #:nodoc:
@@ -14,15 +15,21 @@ module Sunspot
14
15
  # Retrieve all facet objects defined for this search, in order they were
15
16
  # defined. To retrieve an individual facet by name, use #facet()
16
17
  #
17
- attr_reader :facets
18
+ attr_reader :facets, :groups
18
19
  attr_reader :query #:nodoc:
19
20
  attr_accessor :request_handler
21
+
22
+ include HitEnumerable
20
23
 
21
24
  def initialize(connection, setup, query, configuration) #:nodoc:
22
25
  @connection, @setup, @query = connection, setup, query
23
26
  @query.paginate(1, configuration.pagination.default_per_page)
27
+
24
28
  @facets = []
25
29
  @facets_by_name = {}
30
+
31
+ @groups_by_name = {}
32
+ @groups = []
26
33
  end
27
34
 
28
35
  #
@@ -35,7 +42,7 @@ module Sunspot
35
42
  def execute
36
43
  reset
37
44
  params = @query.to_params
38
- @solr_result = @connection.request("/#{request_handler}", params, {:header => {'Content-Type' => 'application/x-www-form-urlencoded'}})
45
+ @solr_result = @connection.post "#{request_handler}", :data => params
39
46
  self
40
47
  end
41
48
 
@@ -78,44 +85,33 @@ module Sunspot
78
85
  #
79
86
  def hits(options = {})
80
87
  if options[:verify]
81
- verified_hits
88
+ super
82
89
  else
83
- @hits ||=
84
- begin
85
- hits = if solr_response && solr_response['docs']
86
- solr_response['docs'].map do |doc|
87
- Hit.new(doc, highlights_for(doc), self)
88
- end
89
- end
90
- paginate_collection(hits || [])
91
- end
90
+ @hits ||= paginate_collection(super)
92
91
  end
93
92
  end
94
93
  alias_method :raw_results, :hits
95
-
94
+
95
+ #
96
+ # The total number of documents matching the query parameters
96
97
  #
97
- # Convenience method to iterate over hit and result objects. Block is
98
- # yielded a Sunspot::Server::Hit instance and a Sunspot::Server::Result
99
- # instance.
98
+ # ==== Returns
100
99
  #
101
- # Note that this method iterates over verified hits (see #hits method
102
- # for more information).
100
+ # Integer:: Total matching documents
103
101
  #
104
- def each_hit_with_result
105
- verified_hits.each do |hit|
106
- yield(hit, hit.result)
107
- end
102
+ def total
103
+ @total ||= solr_response['numFound'] || 0
108
104
  end
109
105
 
110
106
  #
111
- # The total number of documents matching the query parameters
107
+ # The time elapsed to generate the Solr response
112
108
  #
113
109
  # ==== Returns
114
110
  #
115
- # Integer:: Total matching documents
111
+ # Integer:: Query runtime in milliseconds
116
112
  #
117
- def total
118
- @total ||= solr_response['numFound'] || 0
113
+ def query_time
114
+ @query_time ||= solr_response_header['QTime']
119
115
  end
120
116
 
121
117
  #
@@ -167,6 +163,12 @@ module Sunspot
167
163
  end
168
164
  end
169
165
  end
166
+
167
+ def group(name)
168
+ if name
169
+ @groups_by_name[name.to_sym]
170
+ end
171
+ end
170
172
 
171
173
  #
172
174
  # Deprecated in favor of optional second argument to #facet
@@ -178,19 +180,9 @@ module Sunspot
178
180
  def facet_response #:nodoc:
179
181
  @solr_result['facet_counts']
180
182
  end
181
-
182
- #
183
- # Get the data accessor that will be used to load a particular class out of
184
- # persistent storage. Data accessors can implement any methods that may be
185
- # useful for refining how data is loaded out of storage. When building a
186
- # search manually (e.g., using the Sunspot#new_search method), this should
187
- # be used before calling #execute(). Use the
188
- # Sunspot::DSL::Search#data_accessor_for method when building searches using
189
- # the block DSL.
190
- #
191
- def data_accessor_for(clazz) #:nodoc:
192
- (@data_accessors ||= {})[clazz.name.to_sym] ||=
193
- Adapters::DataAccessor.create(clazz)
183
+
184
+ def group_response #:nodoc:
185
+ @solr_result['grouped']
194
186
  end
195
187
 
196
188
  #
@@ -211,31 +203,14 @@ module Sunspot
211
203
  self
212
204
  end
213
205
 
214
- #
215
- # Populate the Hit objects with their instances. This is invoked the first
216
- # time any hit has its instance requested, and all hits are loaded as a
217
- # batch.
218
- #
219
- def populate_hits #:nodoc:
220
- id_hit_hash = Hash.new { |h, k| h[k] = {} }
221
- hits.each do |hit|
222
- id_hit_hash[hit.class_name][hit.primary_key] = hit
223
- end
224
- id_hit_hash.each_pair do |class_name, hits|
225
- ids = hits.map { |id, hit| hit.primary_key }
226
- data_accessor = data_accessor_for(Util.full_const_get(class_name))
227
- hits_for_class = id_hit_hash[class_name]
228
- data_accessor.load_all(ids).each do |result|
229
- hit = hits_for_class.delete(Adapters::InstanceAdapter.adapt(result).id.to_s)
230
- hit.result = result
231
- end
232
- hits_for_class.values.each { |hit| hit.result = nil }
233
- end
234
- end
235
206
 
236
207
  def inspect #:nodoc:
237
208
  "<Sunspot::Search:#{query.to_params.inspect}>"
238
209
  end
210
+
211
+ def add_field_group(field, options = {}) #:nodoc:
212
+ add_group(field.name, FieldGroup.new(field, self, options))
213
+ end
239
214
 
240
215
  def add_field_facet(field, options = {}) #:nodoc:
241
216
  name = (options[:name] || field.name)
@@ -250,6 +225,12 @@ module Sunspot
250
225
  name = (options[:name] || field.name)
251
226
  add_facet(name, DateFacet.new(field, self, options))
252
227
  end
228
+
229
+ def highlights_for(doc) #:nodoc:
230
+ if @solr_result['highlighting']
231
+ @solr_result['highlighting'][doc['id']]
232
+ end
233
+ end
253
234
 
254
235
  private
255
236
 
@@ -265,14 +246,16 @@ module Sunspot
265
246
  @solr_response ||= @solr_result['response'] || {}
266
247
  end
267
248
 
268
- def highlights_for(doc)
269
- if @solr_result['highlighting']
270
- @solr_result['highlighting'][doc['id']]
271
- end
249
+ def solr_response_header
250
+ @solr_response_header ||= @solr_result['responseHeader'] || {}
251
+ end
252
+
253
+ def solr_docs
254
+ solr_response['docs']
272
255
  end
273
256
 
274
257
  def verified_hits
275
- @verified_hits ||= paginate_collection(hits.select { |hit| hit.instance })
258
+ @verified_hits ||= paginate_collection(super)
276
259
  end
277
260
 
278
261
  def paginate_collection(collection)
@@ -283,6 +266,11 @@ module Sunspot
283
266
  @facets << facet
284
267
  @facets_by_name[name.to_sym] = facet
285
268
  end
269
+
270
+ def add_group(name, group)
271
+ @groups << group
272
+ @groups_by_name[name.to_sym] = group
273
+ end
286
274
 
287
275
  # Clear out all the cached ivars so the search can be called again.
288
276
  def reset