kuahyeow-sunspot 0.9.8 → 0.10.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/History.txt +38 -0
  2. data/README.rdoc +40 -3
  3. data/TODO +10 -8
  4. data/VERSION.yml +2 -2
  5. data/bin/sunspot-configure-solr +22 -28
  6. data/bin/sunspot-solr +50 -29
  7. data/lib/sunspot.rb +8 -18
  8. data/lib/sunspot/adapters.rb +1 -1
  9. data/lib/sunspot/composite_setup.rb +13 -15
  10. data/lib/sunspot/configuration.rb +21 -0
  11. data/lib/sunspot/data_extractor.rb +3 -0
  12. data/lib/sunspot/dsl.rb +2 -1
  13. data/lib/sunspot/dsl/field_query.rb +33 -6
  14. data/lib/sunspot/dsl/fields.rb +14 -1
  15. data/lib/sunspot/dsl/fulltext.rb +168 -0
  16. data/lib/sunspot/dsl/query.rb +82 -5
  17. data/lib/sunspot/dsl/query_facet.rb +3 -3
  18. data/lib/sunspot/dsl/restriction.rb +7 -7
  19. data/lib/sunspot/dsl/scope.rb +17 -10
  20. data/lib/sunspot/dsl/search.rb +2 -2
  21. data/lib/sunspot/facet.rb +12 -39
  22. data/lib/sunspot/facet_data.rb +169 -0
  23. data/lib/sunspot/facet_row.rb +5 -27
  24. data/lib/sunspot/field.rb +50 -26
  25. data/lib/sunspot/field_factory.rb +15 -0
  26. data/lib/sunspot/indexer.rb +6 -0
  27. data/lib/sunspot/instantiated_facet.rb +7 -6
  28. data/lib/sunspot/instantiated_facet_row.rb +16 -1
  29. data/lib/sunspot/query.rb +2 -187
  30. data/lib/sunspot/query/boost_query.rb +20 -0
  31. data/lib/sunspot/query/connective.rb +98 -35
  32. data/lib/sunspot/query/dismax.rb +73 -0
  33. data/lib/sunspot/query/field_facet.rb +3 -23
  34. data/lib/sunspot/query/fulltext_base_query.rb +47 -0
  35. data/lib/sunspot/query/highlighting.rb +43 -0
  36. data/lib/sunspot/query/local.rb +24 -0
  37. data/lib/sunspot/query/pagination.rb +3 -4
  38. data/lib/sunspot/query/query.rb +93 -0
  39. data/lib/sunspot/query/query_facet.rb +15 -9
  40. data/lib/sunspot/query/query_facet_row.rb +3 -3
  41. data/lib/sunspot/query/query_field_facet.rb +20 -0
  42. data/lib/sunspot/query/restriction.rb +36 -15
  43. data/lib/sunspot/query/scope.rb +3 -159
  44. data/lib/sunspot/query/sort.rb +84 -15
  45. data/lib/sunspot/query/text_field_boost.rb +15 -0
  46. data/lib/sunspot/schema.rb +7 -25
  47. data/lib/sunspot/search.rb +63 -45
  48. data/lib/sunspot/search/highlight.rb +38 -0
  49. data/lib/sunspot/search/hit.rb +50 -3
  50. data/lib/sunspot/session.rb +40 -11
  51. data/lib/sunspot/setup.rb +47 -10
  52. data/lib/sunspot/text_field_setup.rb +29 -0
  53. data/lib/sunspot/type.rb +4 -4
  54. data/lib/sunspot/util.rb +27 -1
  55. data/solr/solr/conf/schema.xml +54 -40
  56. data/solr/solr/conf/solrconfig.xml +30 -0
  57. data/solr/solr/lib/geoapi-nogenerics-2.1-M2.jar +0 -0
  58. data/solr/solr/lib/gt2-referencing-2.3.1.jar +0 -0
  59. data/solr/solr/lib/jsr108-0.01.jar +0 -0
  60. data/solr/solr/lib/locallucene.jar +0 -0
  61. data/solr/solr/lib/localsolr.jar +0 -0
  62. data/spec/api/indexer/attributes_spec.rb +100 -0
  63. data/spec/api/indexer/batch_spec.rb +46 -0
  64. data/spec/api/indexer/dynamic_fields_spec.rb +33 -0
  65. data/spec/api/indexer/fixed_fields_spec.rb +57 -0
  66. data/spec/api/indexer/fulltext_spec.rb +43 -0
  67. data/spec/api/indexer/removal_spec.rb +46 -0
  68. data/spec/api/indexer/spec_helper.rb +1 -0
  69. data/spec/api/indexer_spec.rb +1 -308
  70. data/spec/api/query/connectives_spec.rb +162 -0
  71. data/spec/api/query/dsl_spec.rb +12 -0
  72. data/spec/api/query/dynamic_fields_spec.rb +149 -0
  73. data/spec/api/query/faceting_spec.rb +272 -0
  74. data/spec/api/query/fulltext_spec.rb +193 -0
  75. data/spec/api/query/highlighting_spec.rb +138 -0
  76. data/spec/api/query/local_spec.rb +54 -0
  77. data/spec/api/query/ordering_pagination_spec.rb +95 -0
  78. data/spec/api/query/scope_spec.rb +266 -0
  79. data/spec/api/query/spec_helper.rb +1 -0
  80. data/spec/api/query/text_field_scoping_spec.rb +30 -0
  81. data/spec/api/query/types_spec.rb +20 -0
  82. data/spec/api/search/dynamic_fields_spec.rb +27 -0
  83. data/spec/api/search/faceting_spec.rb +206 -0
  84. data/spec/api/search/highlighting_spec.rb +65 -0
  85. data/spec/api/search/hits_spec.rb +62 -0
  86. data/spec/api/search/results_spec.rb +52 -0
  87. data/spec/api/search/search_spec.rb +23 -0
  88. data/spec/api/search/spec_helper.rb +1 -0
  89. data/spec/api/session_spec.rb +11 -5
  90. data/spec/api/spec_helper.rb +1 -1
  91. data/spec/helpers/indexer_helper.rb +29 -0
  92. data/spec/helpers/query_helper.rb +13 -0
  93. data/spec/helpers/search_helper.rb +78 -0
  94. data/spec/integration/faceting_spec.rb +1 -1
  95. data/spec/integration/highlighting_spec.rb +22 -0
  96. data/spec/integration/keyword_search_spec.rb +65 -0
  97. data/spec/integration/local_search_spec.rb +56 -0
  98. data/spec/integration/scoped_search_spec.rb +15 -1
  99. data/spec/integration/spec_helper.rb +7 -1
  100. data/spec/mocks/connection.rb +24 -2
  101. data/spec/mocks/photo.rb +1 -1
  102. data/spec/mocks/post.rb +5 -3
  103. data/spec/mocks/super_class.rb +2 -0
  104. data/spec/spec_helper.rb +13 -0
  105. data/tasks/gemspec.rake +20 -8
  106. data/tasks/schema.rake +1 -1
  107. data/tasks/spec.rake +1 -1
  108. data/templates/schema.xml.erb +36 -0
  109. metadata +118 -52
  110. data/lib/sunspot/date_facet.rb +0 -36
  111. data/lib/sunspot/date_facet_row.rb +0 -17
  112. data/lib/sunspot/query/base_query.rb +0 -94
  113. data/lib/sunspot/query/dynamic_query.rb +0 -69
  114. data/lib/sunspot/query/field_query.rb +0 -57
  115. data/lib/sunspot/query_facet.rb +0 -33
  116. data/lib/sunspot/query_facet_row.rb +0 -21
  117. data/spec/api/build_search_spec.rb +0 -1018
  118. data/spec/api/query_spec.rb +0 -153
  119. data/spec/api/search_retrieval_spec.rb +0 -335
  120. data/templates/schema.xml.haml +0 -24
@@ -1,164 +1,8 @@
1
1
  module Sunspot
2
2
  module Query
3
- #
4
- # The Scope class encapsulates a set of restrictions that scope search
5
- # results (as well as query facets rows). This class's API is exposed by
6
- # Query::Query and Query::QueryFacetRow.
7
- #
8
- class Scope
9
- #
10
- # Add a restriction to the query.
11
- #
12
- # ==== Parameters
13
- #
14
- # field_name<Symbol>:: Name of the field to which the restriction applies
15
- # restriction_type<Class,Symbol>::
16
- # Subclass of Sunspot::Query::Restriction::Base, or snake_cased name as symbol
17
- # (e.g., +:equal_to+)
18
- # value<Object>::
19
- # Value against which the restriction applies (e.g. less_than(2) has a
20
- # value of 2)
21
- # negated::
22
- # Whether this restriction should be negated (use add_negated_restriction)
23
- #
24
- def add_restriction(field_name, restriction_type, value, negated = false)
25
- if restriction_type.is_a?(Symbol)
26
- restriction_type = Restriction[restriction_type]
27
- end
28
- add_component(
29
- restriction = restriction_type.new(
30
- build_field(field_name), value, negated
31
- )
32
- )
33
- restriction
34
- end
35
-
36
- #
37
- # Add a negated restriction to the query. The restriction will be taken as
38
- # the opposite of its usual meaning (e.g., an :equal_to restriction will
39
- # be "not equal to".
40
- #
41
- # ==== Parameters
42
- #
43
- # field_name<Symbol>:: Name of the field to which the restriction applies
44
- # restriction_type<Class>::
45
- # Subclass of Sunspot::Query::Restriction::Base to instantiate
46
- # value<Object>::
47
- # Value against which the restriction applies (e.g. less_than(2) has a
48
- # value of 2)
49
- #
50
- def add_negated_restriction(field_name, restriction_type, value)
51
- add_restriction(field_name, restriction_type, value, true)
52
- end
53
-
54
- #
55
- # Add a disjunction to the scope. The disjunction can then take a set of
56
- # restrictions, which are combined with OR semantics.
57
- #
58
- # ==== Returns
59
- #
60
- # Connective::Disjunction:: New disjunction
61
- #
62
- def add_disjunction
63
- add_component(disjunction = Connective::Disjunction.new(setup))
64
- disjunction
65
- end
66
-
67
- #
68
- # Add a conjunction to the scope. In most cases, this will simply return
69
- # the Scope object itself, since scopes by default combine their
70
- # restrictions with OR semantics. The Connective::Disjunction class
71
- # overrides this method to return a Connective::Conjunction.
72
- #
73
- # ==== Returns
74
- #
75
- # Scope:: Self or another scope with conjunctive semantics.
76
- #
77
- def add_conjunction
78
- self
79
- end
80
-
81
- #
82
- # Exclude a particular instance from the search results
83
- #
84
- # ==== Parameters
85
- #
86
- # instance<Object>:: instance to exclude from results
87
- #
88
- def exclude_instance(instance)
89
- add_component(Restriction::SameAs.new(instance, true))
90
- end
91
-
92
- #
93
- # Generate a DynamicQuery instance for the given base name.
94
- # This gives you access to a subset of the Query API but the operations
95
- # apply to dynamic fields inside the dynamic field definition specified
96
- # by +base_name+.
97
- #
98
- # ==== Parameters
99
- #
100
- # base_name<Symbol>::
101
- # Base name of the dynamic field definition to use in the dynamic query
102
- # operations
103
- #
104
- # ==== Returns
105
- #
106
- # DynamicQuery::
107
- # Instance providing dynamic query functionality for the given field
108
- # definitions.
109
- #
110
- def dynamic_query(base_name)
111
- DynamicQuery.new(setup.dynamic_field_factory(base_name), self)
112
- end
113
-
114
- #
115
- # Determine which restriction type to add based on the type of the value.
116
- # Used to interpret query conditions passed as a hash, as well as the
117
- # short-form DSL::Scope#with method.
118
- #
119
- # ==== Parameters
120
- #
121
- # field_name<Symbol>:: Name of the field on which to apply the restriction
122
- # value<Object,Array,Range>:: Value to which to apply to the restriction
123
- #--
124
- # negated<Boolean>:: Whether to negate the restriction.
125
- #
126
- def add_shorthand_restriction(field_name, value, negated = false) #:nodoc:
127
- restriction_type =
128
- case value
129
- when Range
130
- Restriction::Between
131
- when Array
132
- Restriction::AnyOf
133
- else
134
- Restriction::EqualTo
135
- end
136
- add_restriction(field_name, restriction_type, value, negated)
137
- end
138
-
139
- #
140
- # Add a negated shorthand restriction. See #add_shorthand_restriction
141
- #
142
- def add_negated_shorthand_restriction(field_name, value)
143
- add_shorthand_restriction(field_name, value, true)
144
- end
145
-
146
- private
147
-
148
- #
149
- # Build a field with the given field name. Subclasses may override this
150
- # method.
151
- #
152
- def build_field(field_name)
153
- setup.field(field_name)
154
- end
155
-
156
- #
157
- # Return a setup object which can return a field object given a name.
158
- # Subclasses may override this method.
159
- #
160
- def setup
161
- @setup
3
+ class Scope < Connective::Conjunction
4
+ def to_params
5
+ { :fq => @components.map { |component| component.to_boolean_phrase }}
162
6
  end
163
7
  end
164
8
  end
@@ -1,9 +1,12 @@
1
1
  module Sunspot
2
2
  module Query
3
3
  #
4
- # The Sort class is a query component representing a sort by a given field.
4
+ # The classes in this module implement query components that build sort
5
+ # parameters for Solr. As well as regular sort on fields, there are several
6
+ # "special" sorts that allow ordering for metrics calculated during the
7
+ # search.
5
8
  #
6
- class Sort #:nodoc:
9
+ module Sort #:nodoc: all
7
10
  DIRECTIONS = {
8
11
  :asc => 'asc',
9
12
  :ascending => 'asc',
@@ -11,25 +14,91 @@ module Sunspot
11
14
  :descending => 'desc'
12
15
  }
13
16
 
14
- def initialize(field, direction = nil)
15
- if field.multiple?
16
- raise(ArgumentError, "#{field.name} cannot be used for ordering because it is a multiple-value field")
17
+ class <<self
18
+ #
19
+ # Certain field names are "special", referring to specific non-field
20
+ # sorts, which are generally by other metrics associated with hits.
21
+ #
22
+ # XXX I'm not entirely convinced it's a good idea to prevent anyone from
23
+ # ever sorting by a field named 'score', etc.
24
+ #
25
+ def special(name)
26
+ special_class_name = "#{Util.camel_case(name.to_s)}Sort"
27
+ if const_defined?(special_class_name) && special_class_name != 'FieldSort'
28
+ const_get(special_class_name)
29
+ end
17
30
  end
18
- @field, @direction = field, (direction || :asc).to_sym
19
31
  end
20
32
 
21
- def to_param
22
- "#{@field.indexed_name.to_sym} #{direction_for_solr}"
33
+ #
34
+ # Base class for sorts. All subclasses should implement the #to_param
35
+ # method, which is a string that is then concatenated with other sort
36
+ # strings by the SortComposite to form the sort parameter.
37
+ #
38
+ class Abstract
39
+ def initialize(direction)
40
+ @direction = (direction || :asc).to_sym
41
+ end
42
+
43
+ private
44
+
45
+ #
46
+ # Translate fairly forgiving direction argument into solr direction
47
+ #
48
+ def direction_for_solr
49
+ DIRECTIONS[@direction] ||
50
+ raise(
51
+ ArgumentError,
52
+ "Unknown sort direction #{@direction}. Acceptable input is: #{DIRECTIONS.keys.map { |input| input.inspect } * ', '}"
53
+ )
54
+ end
23
55
  end
24
56
 
25
- private
57
+ #
58
+ # A FieldSort is the usual kind of sort, by the value of a particular
59
+ # field, ascending or descending
60
+ #
61
+ class FieldSort < Abstract
62
+ def initialize(field, direction = nil)
63
+ if field.multiple?
64
+ raise(ArgumentError, "#{field.name} cannot be used for ordering because it is a multiple-value field")
65
+ end
66
+ @field, @direction = field, (direction || :asc).to_sym
67
+ end
68
+
69
+ def to_param
70
+ "#{@field.indexed_name.to_sym} #{direction_for_solr}"
71
+ end
72
+ end
26
73
 
27
- def direction_for_solr
28
- DIRECTIONS[@direction] ||
29
- raise(
30
- ArgumentError,
31
- "Unknown sort direction #{@direction}. Acceptable input is: #{DIRECTIONS.keys.map { |input| input.inspect } * ', '}"
32
- )
74
+ #
75
+ # A RandomSort uses Solr's random field functionality to sort results
76
+ # (usually) randomly.
77
+ #
78
+ class RandomSort < Abstract
79
+ def to_param
80
+ "random_#{rand(1<<16)} #{direction_for_solr}"
81
+ end
82
+ end
83
+
84
+ #
85
+ # A ScoreSort sorts by keyword relevance score. This is only useful when
86
+ # performing fulltext search.
87
+ #
88
+ class ScoreSort < Abstract
89
+ def to_param
90
+ "score #{direction_for_solr}"
91
+ end
92
+ end
93
+
94
+ #
95
+ # A DistanceSort sorts by distance from the origin coordinates of a
96
+ # geographical distance search.
97
+ #
98
+ class DistanceSort < Abstract
99
+ def to_param
100
+ "geo_distance #{direction_for_solr}"
101
+ end
33
102
  end
34
103
  end
35
104
  end
@@ -0,0 +1,15 @@
1
+ module Sunspot
2
+ module Query
3
+ class TextFieldBoost #:nodoc:
4
+ def initialize(field, boost = nil)
5
+ @field, @boost = field, boost
6
+ end
7
+
8
+ def to_boosted_field
9
+ boosted_field = @field.indexed_name
10
+ boosted_field.concat("^#{@boost}") if @boost
11
+ boosted_field
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,15 +1,4 @@
1
- using_rubygems = false
2
- begin
3
- require 'haml'
4
- rescue LoadError => e
5
- if using_rubygems
6
- raise(e)
7
- else
8
- using_rubygems = true
9
- require 'rubygems'
10
- retry
11
- end
12
- end
1
+ require 'erb'
13
2
 
14
3
  module Sunspot
15
4
  #
@@ -29,7 +18,9 @@ module Sunspot
29
18
  FieldType.new('sfloat', 'SortableFloat', 'f'),
30
19
  FieldType.new('date', 'Date', 'd'),
31
20
  FieldType.new('sint', 'SortableInt', 'i'),
32
- FieldType.new('string', 'Str', 's')
21
+ FieldType.new('string', 'Str', 's'),
22
+ FieldType.new('sdouble', 'SortableDouble', 'e'),
23
+ FieldType.new('slong', 'SortableLong', 'l')
33
24
  ]
34
25
 
35
26
  FIELD_VARIANTS = [
@@ -89,20 +80,11 @@ module Sunspot
89
80
  end
90
81
 
91
82
  #
92
- # Return an XML representation of this schema using the Haml template
83
+ # Return an XML representation of this schema using the ERB template
93
84
  #
94
85
  def to_xml
95
- template = File.read(
96
- File.join(
97
- File.dirname(__FILE__),
98
- '..',
99
- '..',
100
- 'templates',
101
- 'schema.xml.haml'
102
- )
103
- )
104
- engine = Haml::Engine.new(template)
105
- engine.render(Object.new, :schema => self)
86
+ template = File.join(File.dirname(__FILE__), '..', '..', 'templates', 'schema.xml.erb')
87
+ ERB.new(File.read(template), nil, '-').result(binding)
106
88
  end
107
89
 
108
90
  private
@@ -1,4 +1,6 @@
1
- require File.join(File.dirname(__FILE__), 'search', 'hit')
1
+ %w(hit highlight).each do |file|
2
+ require File.join(File.dirname(__FILE__), 'search', file)
3
+ end
2
4
 
3
5
  module Sunspot
4
6
  #
@@ -14,8 +16,9 @@ module Sunspot
14
16
  # in this case.
15
17
  attr_reader :query
16
18
 
17
- def initialize(connection, setup, query) #:nodoc:
19
+ def initialize(connection, setup, query, configuration) #:nodoc:
18
20
  @connection, @setup, @query = connection, setup, query
21
+ @query.paginate(1, configuration.pagination.default_per_page)
19
22
  end
20
23
 
21
24
  #
@@ -25,11 +28,13 @@ module Sunspot
25
28
  # Sunspot#new_search(), you will need to call this method after building the
26
29
  # query.
27
30
  #
28
- def execute!
31
+ def execute
32
+ reset
29
33
  params = @query.to_params
30
34
  @solr_result = @connection.select(params)
31
35
  self
32
36
  end
37
+ alias_method :execute!, :execute #:nodoc: deprecated
33
38
 
34
39
  #
35
40
  # Get the collection of results as instantiated objects. If WillPaginate is
@@ -60,7 +65,7 @@ module Sunspot
60
65
  # Array:: Ordered collection of Hit objects
61
66
  #
62
67
  def hits
63
- @hits ||= solr_response['docs'].map { |doc| Hit.new(doc, self) }
68
+ @hits ||= solr_response['docs'].map { |doc| Hit.new(doc, highlights_for(doc), self) }
64
69
  end
65
70
  alias_method :raw_results, :hits
66
71
 
@@ -76,29 +81,21 @@ module Sunspot
76
81
  end
77
82
 
78
83
  #
79
- # Get the facet object for the given field. This field will need to have
80
- # been requested as a field facet inside the search block.
81
- #
82
- # ==== Parameters
83
- #
84
- # field_name<Symbol>:: field name for which to get the facet
85
- #
86
- # ==== Returns
84
+ # Get the facet object for the given name. `name` can either be the name
85
+ # given to a query facet, or the field name of a field facet. Returns a
86
+ # Sunspot::Facet object.
87
87
  #
88
- # Sunspot::Facet:: Facet object for the given field
89
- #
90
- def facet(field_name)
91
- (@facets_cache ||= {})[field_name.to_sym] ||=
88
+ def facet(name)
89
+ (@facets_cache ||= {})[name.to_sym] ||=
92
90
  begin
93
- query_facet(field_name) ||
91
+ facet_data = query_facet_data(name) ||
94
92
  begin
95
- field = field(field_name)
96
- date_facet(field) ||
97
- begin
98
- facet_class = field.reference ? InstantiatedFacet : Facet
99
- facet_class.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field)
100
- end
93
+ field = field(name)
94
+ date_facet_data(field) ||
95
+ FacetData::FieldFacetData.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field)
101
96
  end
97
+ facet_class = facet_data.reference ? InstantiatedFacet : Facet
98
+ facet_class.new(facet_data)
102
99
  end
103
100
  end
104
101
 
@@ -132,7 +129,7 @@ module Sunspot
132
129
  (@dynamic_facets_cache ||= {})[[base_name.to_sym, dynamic_name.to_sym]] ||=
133
130
  begin
134
131
  field = @setup.dynamic_field_factory(base_name).build(dynamic_name)
135
- Facet.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field)
132
+ Facet.new(FacetData::FieldFacetData.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field))
136
133
  end
137
134
  end
138
135
 
@@ -145,19 +142,34 @@ module Sunspot
145
142
  # Sunspot::DSL::Search#data_accessor_for method when building searches using
146
143
  # the block DSL.
147
144
  #
148
- def data_accessor_for(clazz)
145
+ def data_accessor_for(clazz) #:nodoc:
149
146
  (@data_accessors ||= {})[clazz.name.to_sym] ||=
150
147
  Adapters::DataAccessor.create(clazz)
151
148
  end
152
149
 
153
150
  #
154
- # Build this search using a DSL block.
151
+ # Build this search using a DSL block. This method can be called more than
152
+ # once on an unexecuted search (e.g., Sunspot.new_search) in order to build
153
+ # a search incrementally.
154
+ #
155
+ # === Example
156
+ #
157
+ # search = Sunspot.new_search(Post)
158
+ # search.build do
159
+ # with(:published_at).less_than Time.now
160
+ # end
161
+ # search.execute!
155
162
  #
156
- def build(&block) #:nodoc:
163
+ def build(&block)
157
164
  Util.instance_eval_or_call(dsl, &block)
158
165
  self
159
166
  end
160
167
 
168
+ #
169
+ # Populate the Hit objects with their instances. This is invoked the first
170
+ # time any hit has its instance requested, and all hits are loaded as a
171
+ # batch.
172
+ #
161
173
  def populate_hits! #:nodoc:
162
174
  id_hit_hash = Hash.new { |h, k| h[k] = {} }
163
175
  hits.each do |hit|
@@ -172,49 +184,55 @@ module Sunspot
172
184
  end
173
185
  end
174
186
 
187
+ def inspect #:nodoc:
188
+ "<Sunspot::Search:#{query.to_params.inspect}>"
189
+ end
190
+
175
191
  private
176
192
 
177
193
  def solr_response
178
194
  @solr_response ||= @solr_result['response']
179
195
  end
180
196
 
181
- def doc_ids
182
- @doc_ids ||= solr_response['docs'].map { |doc| doc['id'] }
183
- end
184
-
185
197
  def dsl
186
- DSL::Search.new(self)
198
+ DSL::Search.new(self, @setup)
187
199
  end
188
200
 
189
- def raw_facet(field)
190
- if field.type == Type::TimeType
191
- @solr_result['facet_counts']['facet_dates'][field.indexed_name]
192
- end || @solr_result['facet_counts']['facet_fields'][field.indexed_name]
193
- end
194
-
195
- def date_facet(field)
201
+ def date_facet_data(field)
196
202
  if field.type == Type::TimeType
197
203
  if @solr_result['facet_counts'].has_key?('facet_dates')
198
204
  if facet_result = @solr_result['facet_counts']['facet_dates'][field.indexed_name]
199
- DateFacet.new(facet_result, field)
205
+ FacetData::DateFacetData.new(facet_result, field)
200
206
  end
201
207
  end
202
208
  end
203
209
  end
204
210
 
205
- def query_facet(name)
211
+ def query_facet_data(name)
206
212
  if query_facet = @query.query_facet(name.to_sym)
207
213
  if @solr_result['facet_counts'].has_key?('facet_queries')
208
- QueryFacet.new(
209
- query_facet,
210
- @solr_result['facet_counts']['facet_queries']
211
- )
214
+ FacetData::QueryFacetData.new(
215
+ query_facet,
216
+ @solr_result['facet_counts']['facet_queries']
217
+ )
212
218
  end
213
219
  end
214
220
  end
215
221
 
222
+ def highlights_for(doc)
223
+ if @solr_result['highlighting']
224
+ @solr_result['highlighting'][doc['id']]
225
+ end
226
+ end
227
+
216
228
  def field(name)
217
229
  @setup.field(name)
218
230
  end
231
+
232
+ # Clear out all the cached ivars so the search can be called again.
233
+ def reset
234
+ @results = @hits = @total = @facets_cache =
235
+ @dynamic_facets_cache = @solr_response = @doc_ids = nil
236
+ end
219
237
  end
220
238
  end