outoftime-sunspot 0.9.6 → 0.9.7
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.
- data/VERSION.yml +2 -2
- data/lib/sunspot.rb +1 -2
- data/lib/sunspot/facet.rb +6 -41
- data/lib/sunspot/facet_data.rb +120 -0
- data/lib/sunspot/facet_row.rb +3 -27
- data/lib/sunspot/instantiated_facet.rb +5 -1
- data/lib/sunspot/instantiated_facet_row.rb +10 -0
- data/lib/sunspot/query.rb +2 -1
- data/lib/sunspot/query/field_facet.rb +2 -0
- data/lib/sunspot/query/field_query.rb +8 -2
- data/lib/sunspot/query/query_facet.rb +2 -1
- data/lib/sunspot/query/query_field_facet.rb +13 -0
- data/lib/sunspot/search.rb +13 -14
- data/spec/api/build_search_spec.rb +21 -0
- data/spec/api/search_retrieval_spec.rb +45 -18
- metadata +5 -8
- data/lib/sunspot/date_facet.rb +0 -36
- data/lib/sunspot/date_facet_row.rb +0 -17
- data/lib/sunspot/query_facet.rb +0 -33
- data/lib/sunspot/query_facet_row.rb +0 -21
data/VERSION.yml
CHANGED
data/lib/sunspot.rb
CHANGED
|
@@ -11,8 +11,7 @@ require File.join(File.dirname(__FILE__), 'light_config')
|
|
|
11
11
|
|
|
12
12
|
%w(util adapters configuration setup composite_setup field field_factory
|
|
13
13
|
data_extractor indexer query search facet facet_row instantiated_facet
|
|
14
|
-
instantiated_facet_row
|
|
15
|
-
session type dsl).each do |filename|
|
|
14
|
+
instantiated_facet_row facet_data session type dsl).each do |filename|
|
|
16
15
|
require File.join(File.dirname(__FILE__), 'sunspot', filename)
|
|
17
16
|
end
|
|
18
17
|
|
data/lib/sunspot/facet.rb
CHANGED
|
@@ -1,51 +1,16 @@
|
|
|
1
|
-
require 'enumerator'
|
|
2
|
-
|
|
3
1
|
module Sunspot
|
|
4
|
-
#
|
|
5
|
-
# The facet class encapsulates the information returned by Solr for a
|
|
6
|
-
# field facet request.
|
|
7
|
-
#
|
|
8
|
-
# See http://wiki.apache.org/solr/SolrFacetingOverview for more information
|
|
9
|
-
# on Solr's faceting capabilities.
|
|
10
|
-
#
|
|
11
2
|
class Facet
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def initialize(facet_values, field) #:nodoc:
|
|
15
|
-
@facet_values, @field = facet_values, field
|
|
3
|
+
def initialize(facet_data)
|
|
4
|
+
@facet_data = facet_data
|
|
16
5
|
end
|
|
17
6
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
# ==== Returns
|
|
21
|
-
#
|
|
22
|
-
# Symbol:: The field name
|
|
23
|
-
#
|
|
24
|
-
def field_name
|
|
25
|
-
@field.name
|
|
7
|
+
def name
|
|
8
|
+
@facet_data.name
|
|
26
9
|
end
|
|
10
|
+
alias_method :field_name, :name
|
|
27
11
|
|
|
28
|
-
# The rows returned for this facet.
|
|
29
|
-
#
|
|
30
|
-
# ==== Returns
|
|
31
|
-
#
|
|
32
|
-
# Array:: Collection of FacetRow objects, in the order returned by Solr
|
|
33
|
-
#
|
|
34
12
|
def rows
|
|
35
|
-
@rows
|
|
36
|
-
begin
|
|
37
|
-
rows = []
|
|
38
|
-
@facet_values.each_slice(2) do |pair|
|
|
39
|
-
rows << new_row(pair)
|
|
40
|
-
end
|
|
41
|
-
rows
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
private
|
|
46
|
-
|
|
47
|
-
def new_row(pair)
|
|
48
|
-
FacetRow.new(pair, self)
|
|
13
|
+
@facet_data.rows { |value, count| FacetRow.new(value, count) }
|
|
49
14
|
end
|
|
50
15
|
end
|
|
51
16
|
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require 'enumerator'
|
|
2
|
+
|
|
3
|
+
module Sunspot
|
|
4
|
+
module FacetData
|
|
5
|
+
class Abstract
|
|
6
|
+
attr_reader :field #:nodoc:
|
|
7
|
+
|
|
8
|
+
def reference
|
|
9
|
+
@field.reference if @field
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def cast(value)
|
|
13
|
+
if @field
|
|
14
|
+
@field.cast(value)
|
|
15
|
+
else
|
|
16
|
+
value
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def row_value(value)
|
|
21
|
+
cast(value)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class FieldFacetData < Abstract
|
|
26
|
+
def initialize(facet_values, field) #:nodoc:
|
|
27
|
+
@facet_values, @field = facet_values, field
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# The name of the field that contains this facet's values
|
|
31
|
+
#
|
|
32
|
+
# ==== Returns
|
|
33
|
+
#
|
|
34
|
+
# Symbol:: The field name
|
|
35
|
+
#
|
|
36
|
+
def name
|
|
37
|
+
@field.name
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The rows returned for this facet.
|
|
41
|
+
#
|
|
42
|
+
# ==== Returns
|
|
43
|
+
#
|
|
44
|
+
# Array:: Collection of FacetRow objects, in the order returned by Solr
|
|
45
|
+
#
|
|
46
|
+
def rows
|
|
47
|
+
@rows ||=
|
|
48
|
+
begin
|
|
49
|
+
rows = []
|
|
50
|
+
@facet_values.each_slice(2) do |value, count|
|
|
51
|
+
rows << yield(row_value(value), count)
|
|
52
|
+
end
|
|
53
|
+
rows
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class DateFacetData < FieldFacetData
|
|
59
|
+
def initialize(facet_values, field) #:nodoc:
|
|
60
|
+
@gap = facet_values.delete('gap')[/\+(\d+)SECONDS/,1].to_i
|
|
61
|
+
%w(start end).each { |key| facet_values.delete(key) }
|
|
62
|
+
super(facet_values.to_a.flatten, field)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Get the rows of this date facet, which are instances of DateFacetRow.
|
|
67
|
+
# The rows will always be sorted in chronological order.
|
|
68
|
+
#
|
|
69
|
+
#--
|
|
70
|
+
#
|
|
71
|
+
# The date facet info comes back from Solr as a hash, so we need to sort
|
|
72
|
+
# it manually. FIXME this currently assumes we want to do a "lexical"
|
|
73
|
+
# sort, but we should support count sort as well, even if it's not a
|
|
74
|
+
# common use case.
|
|
75
|
+
#
|
|
76
|
+
def rows(&block)
|
|
77
|
+
super(&block).sort { |a, b| a.value.first <=> b.value.first }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def row_value(value)
|
|
83
|
+
cast(value)..(cast(value) + @gap)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class QueryFacetData < Abstract
|
|
88
|
+
def initialize(outgoing_query_facet, row_data) #:nodoc:
|
|
89
|
+
@outgoing_query_facet, @row_data = outgoing_query_facet, row_data
|
|
90
|
+
@field = @outgoing_query_facet.field
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def name
|
|
94
|
+
outgoing_query_facet.name
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
#
|
|
98
|
+
# Get the rows associated with this query facet. Returned rows are always
|
|
99
|
+
# ordered by count.
|
|
100
|
+
#
|
|
101
|
+
# ==== Returns
|
|
102
|
+
#
|
|
103
|
+
# Array:: Collection of QueryFacetRow objects, ordered by count
|
|
104
|
+
#
|
|
105
|
+
def rows
|
|
106
|
+
@rows ||=
|
|
107
|
+
begin
|
|
108
|
+
rows = []
|
|
109
|
+
for row in @outgoing_query_facet.rows
|
|
110
|
+
row_query = row.to_boolean_phrase
|
|
111
|
+
if @row_data.has_key?(row_query)
|
|
112
|
+
rows << yield(row.label, @row_data[row_query])
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
rows.sort! { |x, y| y.count <=> x.count }
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
data/lib/sunspot/facet_row.rb
CHANGED
|
@@ -1,34 +1,10 @@
|
|
|
1
1
|
module Sunspot
|
|
2
2
|
# This class encapsulates a facet row (value) for a facet.
|
|
3
3
|
class FacetRow
|
|
4
|
-
|
|
5
|
-
@pair, @facet = pair, facet
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
# The value associated with the facet. This will be cast according to the
|
|
9
|
-
# field's type; so, for an integer field, this method will return an
|
|
10
|
-
# integer, etc.
|
|
11
|
-
#
|
|
12
|
-
# Note that <strong>+Time+ fields will always return facet values in
|
|
13
|
-
# UTC</strong>.
|
|
14
|
-
#
|
|
15
|
-
# ==== Returns
|
|
16
|
-
#
|
|
17
|
-
# Object:: The value associated with the row, cast to the appropriate type
|
|
18
|
-
#
|
|
19
|
-
def value
|
|
20
|
-
@value ||= @facet.field.cast(@pair[0])
|
|
21
|
-
end
|
|
4
|
+
attr_reader :value, :count
|
|
22
5
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
#
|
|
26
|
-
# ==== Returns
|
|
27
|
-
#
|
|
28
|
-
# Integer:: Document count for this value
|
|
29
|
-
#
|
|
30
|
-
def count
|
|
31
|
-
@count ||= @pair[1]
|
|
6
|
+
def initialize(value, count) #:nodoc:
|
|
7
|
+
@value, @count = value, count
|
|
32
8
|
end
|
|
33
9
|
end
|
|
34
10
|
end
|
|
@@ -15,7 +15,7 @@ module Sunspot
|
|
|
15
15
|
#
|
|
16
16
|
def populate_instances! #:nodoc:
|
|
17
17
|
ids = rows.map { |row| row.value }
|
|
18
|
-
reference_class = Sunspot::Util.full_const_get(@
|
|
18
|
+
reference_class = Sunspot::Util.full_const_get(@facet_data.reference.to_s)
|
|
19
19
|
accessor = Adapters::DataAccessor.create(reference_class)
|
|
20
20
|
instance_map = accessor.load_all(ids).inject({}) do |map, instance|
|
|
21
21
|
map[Adapters::InstanceAdapter.adapt(instance).id] = instance
|
|
@@ -26,6 +26,10 @@ module Sunspot
|
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
def rows
|
|
30
|
+
@facet_data.rows { |value, count| InstantiatedFacetRow.new(value, count, self) }
|
|
31
|
+
end
|
|
32
|
+
|
|
29
33
|
private
|
|
30
34
|
|
|
31
35
|
#
|
|
@@ -2,6 +2,16 @@ module Sunspot
|
|
|
2
2
|
class InstantiatedFacetRow < FacetRow
|
|
3
3
|
attr_writer :instance
|
|
4
4
|
|
|
5
|
+
def initialize(value, count, facet)
|
|
6
|
+
super(value, count)
|
|
7
|
+
@facet = facet
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Get the persistent object referenced by this row's value. Instances are
|
|
12
|
+
# batch-lazy-loaded, which means that for a given facet, all of the
|
|
13
|
+
# instances are loaded the first time any row's instance is requested.
|
|
14
|
+
#
|
|
5
15
|
def instance
|
|
6
16
|
unless defined?(@instance)
|
|
7
17
|
@facet.populate_instances!
|
data/lib/sunspot/query.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
%w(base_query scope field_query connective dynamic_query field_facet query_facet
|
|
2
|
-
query_facet_row pagination restriction sort
|
|
2
|
+
query_facet_row query_field_facet pagination restriction sort
|
|
3
|
+
sort_composite).each do |file|
|
|
3
4
|
require File.join(File.dirname(__FILE__), 'query', file)
|
|
4
5
|
end
|
|
5
6
|
|
|
@@ -18,7 +18,14 @@ module Sunspot
|
|
|
18
18
|
# FieldFacet:: The field facet object
|
|
19
19
|
#
|
|
20
20
|
def add_field_facet(field_name, options = nil)
|
|
21
|
-
|
|
21
|
+
options ||= {}
|
|
22
|
+
facet =
|
|
23
|
+
if only = options.delete(:only)
|
|
24
|
+
query_facets[field_name.to_sym] = QueryFieldFacet.new(@setup.field(field_name), only)
|
|
25
|
+
else
|
|
26
|
+
FieldFacet.build(build_field(field_name), options)
|
|
27
|
+
end
|
|
28
|
+
add_component(facet)
|
|
22
29
|
end
|
|
23
30
|
|
|
24
31
|
#
|
|
@@ -38,7 +45,6 @@ module Sunspot
|
|
|
38
45
|
def add_query_facet(name)
|
|
39
46
|
add_component(facet = QueryFacet.new(name, setup))
|
|
40
47
|
query_facets[name.to_sym] = facet
|
|
41
|
-
facet
|
|
42
48
|
end
|
|
43
49
|
|
|
44
50
|
#
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Sunspot
|
|
2
|
+
module Query
|
|
3
|
+
class QueryFieldFacet < QueryFacet
|
|
4
|
+
def initialize(field, values)
|
|
5
|
+
super(field.name)
|
|
6
|
+
@field = field
|
|
7
|
+
values.each do |value|
|
|
8
|
+
add_row(value).add_component(Restriction::EqualTo.new(field, value))
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/sunspot/search.rb
CHANGED
|
@@ -90,15 +90,14 @@ module Sunspot
|
|
|
90
90
|
def facet(field_name)
|
|
91
91
|
(@facets_cache ||= {})[field_name.to_sym] ||=
|
|
92
92
|
begin
|
|
93
|
-
|
|
93
|
+
facet_data = query_facet_data(field_name) ||
|
|
94
94
|
begin
|
|
95
95
|
field = field(field_name)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
facet_class = field.reference ? InstantiatedFacet : Facet
|
|
99
|
-
facet_class.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field)
|
|
100
|
-
end
|
|
96
|
+
date_facet_data(field) ||
|
|
97
|
+
FacetData::FieldFacetData.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field)
|
|
101
98
|
end
|
|
99
|
+
facet_class = facet_data.reference ? InstantiatedFacet : Facet
|
|
100
|
+
facet_class.new(facet_data)
|
|
102
101
|
end
|
|
103
102
|
end
|
|
104
103
|
|
|
@@ -132,7 +131,7 @@ module Sunspot
|
|
|
132
131
|
(@dynamic_facets_cache ||= {})[[base_name.to_sym, dynamic_name.to_sym]] ||=
|
|
133
132
|
begin
|
|
134
133
|
field = @setup.dynamic_field_factory(base_name).build(dynamic_name)
|
|
135
|
-
Facet.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field)
|
|
134
|
+
Facet.new(FacetData::FieldFacetData.new(@solr_result['facet_counts']['facet_fields'][field.indexed_name], field))
|
|
136
135
|
end
|
|
137
136
|
end
|
|
138
137
|
|
|
@@ -192,23 +191,23 @@ module Sunspot
|
|
|
192
191
|
end || @solr_result['facet_counts']['facet_fields'][field.indexed_name]
|
|
193
192
|
end
|
|
194
193
|
|
|
195
|
-
def
|
|
194
|
+
def date_facet_data(field)
|
|
196
195
|
if field.type == Type::TimeType
|
|
197
196
|
if @solr_result['facet_counts'].has_key?('facet_dates')
|
|
198
197
|
if facet_result = @solr_result['facet_counts']['facet_dates'][field.indexed_name]
|
|
199
|
-
|
|
198
|
+
FacetData::DateFacetData.new(facet_result, field)
|
|
200
199
|
end
|
|
201
200
|
end
|
|
202
201
|
end
|
|
203
202
|
end
|
|
204
203
|
|
|
205
|
-
def
|
|
204
|
+
def query_facet_data(name)
|
|
206
205
|
if query_facet = @query.query_facet(name.to_sym)
|
|
207
206
|
if @solr_result['facet_counts'].has_key?('facet_queries')
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
207
|
+
FacetData::QueryFacetData.new(
|
|
208
|
+
query_facet,
|
|
209
|
+
@solr_result['facet_counts']['facet_queries']
|
|
210
|
+
)
|
|
212
211
|
end
|
|
213
212
|
end
|
|
214
213
|
end
|
|
@@ -860,6 +860,27 @@ describe 'Search' do
|
|
|
860
860
|
end
|
|
861
861
|
end
|
|
862
862
|
|
|
863
|
+
it 'builds query facets when passed :only argument to field facet declaration' do
|
|
864
|
+
session.search Post do
|
|
865
|
+
facet :category_ids, :only => [1, 3]
|
|
866
|
+
end
|
|
867
|
+
connection.should have_last_search_with(
|
|
868
|
+
:"facet.query" => ['category_ids_im:1', 'category_ids_im:3']
|
|
869
|
+
)
|
|
870
|
+
end
|
|
871
|
+
|
|
872
|
+
it 'converts limited query facet values to the correct type' do
|
|
873
|
+
session.search Post do
|
|
874
|
+
facet :published_at, :only => [Time.utc(2009, 8, 28, 15, 33), Time.utc(2008,8, 28, 15, 33)]
|
|
875
|
+
end
|
|
876
|
+
connection.should have_last_search_with(
|
|
877
|
+
:"facet.query" => [
|
|
878
|
+
'published_at_d:2009\-08\-28T15\:33\:00Z',
|
|
879
|
+
'published_at_d:2008\-08\-28T15\:33\:00Z'
|
|
880
|
+
]
|
|
881
|
+
)
|
|
882
|
+
end
|
|
883
|
+
|
|
863
884
|
it 'should allow faceting by dynamic string field' do
|
|
864
885
|
session.search Post do
|
|
865
886
|
dynamic :custom_string do
|
|
@@ -154,7 +154,7 @@ describe 'retrieving search' do
|
|
|
154
154
|
end
|
|
155
155
|
facet_values(result, :published_at).should ==
|
|
156
156
|
[Time.gm(2009, 04, 07, 20, 25, 23),
|
|
157
|
-
|
|
157
|
+
Time.gm(2009, 04, 07, 20, 26, 19)]
|
|
158
158
|
end
|
|
159
159
|
|
|
160
160
|
it 'should return date facet' do
|
|
@@ -168,7 +168,7 @@ describe 'retrieving search' do
|
|
|
168
168
|
end
|
|
169
169
|
facet_values(result, :expire_date).should ==
|
|
170
170
|
[Date.new(2009, 07, 13),
|
|
171
|
-
|
|
171
|
+
Date.new(2009, 04, 01)]
|
|
172
172
|
end
|
|
173
173
|
|
|
174
174
|
it 'should return boolean facet' do
|
|
@@ -233,6 +233,21 @@ describe 'retrieving search' do
|
|
|
233
233
|
facet.rows.first.count.should == 3
|
|
234
234
|
end
|
|
235
235
|
|
|
236
|
+
it 'returns limited field facet' do
|
|
237
|
+
stub_query_facet(
|
|
238
|
+
'category_ids_im:1' => 3,
|
|
239
|
+
'category_ids_im:3' => 1
|
|
240
|
+
)
|
|
241
|
+
search = session.search(Post) do
|
|
242
|
+
facet :category_ids, :only => [1, 3, 5]
|
|
243
|
+
end
|
|
244
|
+
facet = search.facet(:category_ids)
|
|
245
|
+
facet.rows.first.value.should == 1
|
|
246
|
+
facet.rows.first.count.should == 3
|
|
247
|
+
facet.rows.last.value.should == 3
|
|
248
|
+
facet.rows.last.count.should == 1
|
|
249
|
+
end
|
|
250
|
+
|
|
236
251
|
it 'should return dynamic string facet' do
|
|
237
252
|
stub_facet(:"custom_string:test_s", 'two' => 2, 'one' => 1)
|
|
238
253
|
result = session.search(Post) { dynamic(:custom_string) { facet(:test) }}
|
|
@@ -246,6 +261,18 @@ describe 'retrieving search' do
|
|
|
246
261
|
result.facet(:blog_id).rows.map { |row| row.instance }.should == blogs
|
|
247
262
|
end
|
|
248
263
|
|
|
264
|
+
it 'returns instantiated facet values for limited field facet' do
|
|
265
|
+
blogs = Array.new(2) { Blog.new }
|
|
266
|
+
stub_query_facet(
|
|
267
|
+
"blog_id_i:#{blogs[0].id}" => 3,
|
|
268
|
+
"blog_id_i:#{blogs[1].id}" => 1
|
|
269
|
+
)
|
|
270
|
+
search = session.search(Post) do
|
|
271
|
+
facet(:blog_id, :only => blogs.map { |blog| blog.id })
|
|
272
|
+
end
|
|
273
|
+
search.facet(:blog_id).rows.map { |row| row.instance }.should == blogs
|
|
274
|
+
end
|
|
275
|
+
|
|
249
276
|
it 'should only query the persistent store once for an instantiated facet' do
|
|
250
277
|
query_count = Blog.query_count
|
|
251
278
|
blogs = Array.new(2) { Blog.new }
|
|
@@ -268,9 +295,9 @@ describe 'retrieving search' do
|
|
|
268
295
|
end
|
|
269
296
|
response = {
|
|
270
297
|
'response' => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
298
|
+
'docs' => docs,
|
|
299
|
+
'numFound' => count
|
|
300
|
+
}
|
|
274
301
|
}
|
|
275
302
|
connection.stub!(:select).and_return(response)
|
|
276
303
|
end
|
|
@@ -278,11 +305,11 @@ describe 'retrieving search' do
|
|
|
278
305
|
def stub_results(*results)
|
|
279
306
|
stub_full_results(
|
|
280
307
|
*results.map do |result|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
308
|
+
if result.is_a?(Integer)
|
|
309
|
+
result
|
|
310
|
+
else
|
|
311
|
+
{ 'instance' => result }
|
|
312
|
+
end
|
|
286
313
|
end
|
|
287
314
|
)
|
|
288
315
|
end
|
|
@@ -290,20 +317,20 @@ describe 'retrieving search' do
|
|
|
290
317
|
def stub_facet(name, values)
|
|
291
318
|
connection.stub!(:select).and_return(
|
|
292
319
|
'facet_counts' => {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
320
|
+
'facet_fields' => {
|
|
321
|
+
name.to_s => values.to_a.sort_by { |value, count| -count }.flatten
|
|
322
|
+
}
|
|
323
|
+
}
|
|
297
324
|
)
|
|
298
325
|
end
|
|
299
326
|
|
|
300
327
|
def stub_date_facet(name, gap, values)
|
|
301
328
|
connection.stub!(:select).and_return(
|
|
302
329
|
'facet_counts' => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
330
|
+
'facet_dates' => {
|
|
331
|
+
name.to_s => { 'gap' => "+#{gap}SECONDS" }.merge(values)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
307
334
|
)
|
|
308
335
|
end
|
|
309
336
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: outoftime-sunspot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mat Brown
|
|
@@ -12,7 +12,7 @@ autorequire:
|
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
14
|
|
|
15
|
-
date: 2009-08-
|
|
15
|
+
date: 2009-08-28 00:00:00 -07:00
|
|
16
16
|
default_executable:
|
|
17
17
|
dependencies:
|
|
18
18
|
- !ruby/object:Gem::Dependency
|
|
@@ -99,8 +99,6 @@ files:
|
|
|
99
99
|
- lib/sunspot/composite_setup.rb
|
|
100
100
|
- lib/sunspot/configuration.rb
|
|
101
101
|
- lib/sunspot/data_extractor.rb
|
|
102
|
-
- lib/sunspot/date_facet.rb
|
|
103
|
-
- lib/sunspot/date_facet_row.rb
|
|
104
102
|
- lib/sunspot/dsl.rb
|
|
105
103
|
- lib/sunspot/dsl/field_query.rb
|
|
106
104
|
- lib/sunspot/dsl/fields.rb
|
|
@@ -110,6 +108,7 @@ files:
|
|
|
110
108
|
- lib/sunspot/dsl/scope.rb
|
|
111
109
|
- lib/sunspot/dsl/search.rb
|
|
112
110
|
- lib/sunspot/facet.rb
|
|
111
|
+
- lib/sunspot/facet_data.rb
|
|
113
112
|
- lib/sunspot/facet_row.rb
|
|
114
113
|
- lib/sunspot/field.rb
|
|
115
114
|
- lib/sunspot/field_factory.rb
|
|
@@ -125,12 +124,11 @@ files:
|
|
|
125
124
|
- lib/sunspot/query/pagination.rb
|
|
126
125
|
- lib/sunspot/query/query_facet.rb
|
|
127
126
|
- lib/sunspot/query/query_facet_row.rb
|
|
127
|
+
- lib/sunspot/query/query_field_facet.rb
|
|
128
128
|
- lib/sunspot/query/restriction.rb
|
|
129
129
|
- lib/sunspot/query/scope.rb
|
|
130
130
|
- lib/sunspot/query/sort.rb
|
|
131
131
|
- lib/sunspot/query/sort_composite.rb
|
|
132
|
-
- lib/sunspot/query_facet.rb
|
|
133
|
-
- lib/sunspot/query_facet_row.rb
|
|
134
132
|
- lib/sunspot/schema.rb
|
|
135
133
|
- lib/sunspot/search.rb
|
|
136
134
|
- lib/sunspot/search/hit.rb
|
|
@@ -189,7 +187,6 @@ files:
|
|
|
189
187
|
- templates/schema.xml.haml
|
|
190
188
|
has_rdoc: true
|
|
191
189
|
homepage: http://github.com/outoftime/sunspot
|
|
192
|
-
licenses:
|
|
193
190
|
post_install_message:
|
|
194
191
|
rdoc_options:
|
|
195
192
|
- --charset=UTF-8
|
|
@@ -215,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
215
212
|
requirements: []
|
|
216
213
|
|
|
217
214
|
rubyforge_project:
|
|
218
|
-
rubygems_version: 1.
|
|
215
|
+
rubygems_version: 1.2.0
|
|
219
216
|
signing_key:
|
|
220
217
|
specification_version: 3
|
|
221
218
|
summary: Library for expressive, powerful interaction with the Solr search engine
|
data/lib/sunspot/date_facet.rb
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
module Sunspot
|
|
2
|
-
#
|
|
3
|
-
# Date facets are retrieved by passing a :time_range key into the
|
|
4
|
-
# DSL::FieldQuery#facet options. They are only available for Date and Time
|
|
5
|
-
# type fields. The #value for date facet rows is a Range object encapsulating
|
|
6
|
-
# the time range covered by the row.
|
|
7
|
-
#
|
|
8
|
-
class DateFacet < Facet
|
|
9
|
-
def initialize(facet_values, field) #:nodoc:
|
|
10
|
-
@gap = facet_values.delete('gap')[/\+(\d+)SECONDS/,1].to_i
|
|
11
|
-
%w(start end).each { |key| facet_values.delete(key) }
|
|
12
|
-
super(facet_values.to_a.flatten, field)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
#
|
|
16
|
-
# Get the rows of this date facet, which are instances of DateFacetRow.
|
|
17
|
-
# The rows will always be sorted in chronological order.
|
|
18
|
-
#
|
|
19
|
-
#--
|
|
20
|
-
#
|
|
21
|
-
# The date facet info comes back from Solr as a hash, so we need to sort
|
|
22
|
-
# it manually. FIXME this currently assumes we want to do a "lexical"
|
|
23
|
-
# sort, but we should support count sort as well, even if it's not a
|
|
24
|
-
# common use case.
|
|
25
|
-
#
|
|
26
|
-
def rows
|
|
27
|
-
super.sort { |a, b| a.value.first <=> b.value.first }
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def new_row(pair)
|
|
33
|
-
DateFacetRow.new(pair, @gap, self)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
module Sunspot
|
|
2
|
-
#TODO document
|
|
3
|
-
class DateFacetRow < FacetRow
|
|
4
|
-
def initialize(pair, gap, facet)
|
|
5
|
-
@gap = gap
|
|
6
|
-
super(pair, facet)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def value
|
|
10
|
-
@value ||=
|
|
11
|
-
begin
|
|
12
|
-
start_date = @facet.field.cast(@pair[0])
|
|
13
|
-
Range.new(start_date, start_date + @gap)
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
data/lib/sunspot/query_facet.rb
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
module Sunspot
|
|
2
|
-
#
|
|
3
|
-
# QueryFacet instances encapsulate a set of query facet results. Each facet
|
|
4
|
-
# corresponds to a group of rows defined inside a DSL::FieldQuery#facet block.
|
|
5
|
-
#
|
|
6
|
-
class QueryFacet
|
|
7
|
-
def initialize(outgoing_query_facet, row_data) #:nodoc:
|
|
8
|
-
@outgoing_query_facet, @row_data = outgoing_query_facet, row_data
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
#
|
|
12
|
-
# Get the rows associated with this query facet. Returned rows are always
|
|
13
|
-
# ordered by count.
|
|
14
|
-
#
|
|
15
|
-
# ==== Returns
|
|
16
|
-
#
|
|
17
|
-
# Array:: Collection of QueryFacetRow objects, ordered by count
|
|
18
|
-
#
|
|
19
|
-
def rows
|
|
20
|
-
@rows ||=
|
|
21
|
-
begin
|
|
22
|
-
rows = []
|
|
23
|
-
for row in @outgoing_query_facet.rows
|
|
24
|
-
row_query = row.to_boolean_phrase
|
|
25
|
-
if @row_data.has_key?(row_query)
|
|
26
|
-
rows << QueryFacetRow.new(row.label, @row_data[row_query])
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
rows.sort! { |x, y| y.count <=> x.count }
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
module Sunspot
|
|
2
|
-
#
|
|
3
|
-
# Objects of this class encapsulate a single query facet row returned for a
|
|
4
|
-
# query facet.
|
|
5
|
-
#
|
|
6
|
-
class QueryFacetRow
|
|
7
|
-
#
|
|
8
|
-
# This is the "label" passed into the query facet row when it is defined in
|
|
9
|
-
# the search.
|
|
10
|
-
#
|
|
11
|
-
attr_reader :value
|
|
12
|
-
#
|
|
13
|
-
# Number of documents in the result set that match this facet's scope.
|
|
14
|
-
#
|
|
15
|
-
attr_reader :count
|
|
16
|
-
|
|
17
|
-
def initialize(value, count) #:nodoc:
|
|
18
|
-
@value, @count = value, count
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|