forked from sunspot/sunspot
/
sort.rb
95 lines (87 loc) · 2.81 KB
/
sort.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
module Sunspot
module Query
#
# The classes in this module implement query components that build sort
# parameters for Solr. As well as regular sort on fields, there are several
# "special" sorts that allow ordering for metrics calculated during the
# search.
#
module Sort #:nodoc: all
DIRECTIONS = {
:asc => 'asc',
:ascending => 'asc',
:desc => 'desc',
:descending => 'desc'
}
class <<self
#
# Certain field names are "special", referring to specific non-field
# sorts, which are generally by other metrics associated with hits.
#
# XXX I'm not entirely convinced it's a good idea to prevent anyone from
# ever sorting by a field named 'score', etc.
#
def special(name)
special_class_name = "#{Util.camel_case(name.to_s)}Sort"
if const_defined?(special_class_name) && special_class_name != 'FieldSort'
const_get(special_class_name)
end
end
end
#
# Base class for sorts. All subclasses should implement the #to_param
# method, which is a string that is then concatenated with other sort
# strings by the SortComposite to form the sort parameter.
#
class Abstract
def initialize(direction)
@direction = (direction || :asc).to_sym
end
private
#
# Translate fairly forgiving direction argument into solr direction
#
def direction_for_solr
DIRECTIONS[@direction] ||
raise(
ArgumentError,
"Unknown sort direction #{@direction}. Acceptable input is: #{DIRECTIONS.keys.map { |input| input.inspect } * ', '}"
)
end
end
#
# A FieldSort is the usual kind of sort, by the value of a particular
# field, ascending or descending
#
class FieldSort < Abstract
def initialize(field, direction = nil)
if field.multiple?
raise(ArgumentError, "#{field.name} cannot be used for ordering because it is a multiple-value field")
end
@field, @direction = field, (direction || :asc).to_sym
end
def to_param
"#{@field.indexed_name.to_sym} #{direction_for_solr}"
end
end
#
# A RandomSort uses Solr's random field functionality to sort results
# (usually) randomly.
#
class RandomSort < Abstract
def to_param
"random_#{rand(1<<16)} #{direction_for_solr}"
end
end
#
# A ScoreSort sorts by keyword relevance score. This is only useful when
# performing fulltext search.
#
class ScoreSort < Abstract
def to_param
"score #{direction_for_solr}"
end
end
end
end
end