elasticsearch_helper.rb
3.62 KB
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
module ElasticsearchHelper
def searchable_types
{
:all => _("All results"),
:text_article => _("Articles"),
:uploaded_file => _("Files"),
:community => _("Communities"),
:event => _("Events"),
:person => _("People")
}
end
def sort_types
sorts = {
:relevance => _("Relevance"),
:lexical => _("Alphabetical"),
:more_recent => _("More recent")
}
selected_type = (params[:selected_type] || nil)
if selected_type and selected_type.to_sym != :all
klass = selected_type.to_s.classify.constantize
sorts.update klass.specific_sort if klass.respond_to? :specific_sort
end
sorts
end
def process_results
selected_type = (params[:selected_type].presence|| :all).to_sym
selected_type == :all ? search_from_all_models : search_from_model(selected_type)
end
private
def search_from_all_models
begin
filter = (params[:filter] || "").to_sym
query = get_query params[:query], sort_by: get_sort_by(filter), categories: params[:categories]
Elasticsearch::Model.search(query,searchable_models, size: default_per_page(params[:per_page])).page(params[:page]).records
rescue
[]
end
end
def search_from_model(model)
begin
klass = model.to_s.classify.constantize
filter = (params[:filter] || "").to_sym
query = get_query params[:query], klass: klass, sort_by: get_sort_by(filter ,klass), categories: params[:categories]
klass.search(query, size: default_per_page(params[:per_page])).page(params[:page]).records
rescue
[]
end
end
def default_per_page(per_page=nil)
per_page || 10
end
def get_sort_by(sort_by, klass=nil)
case sort_by
when :lexical
{"name.raw" => {"order" => "asc"}}
when :more_recent
{"created_at" => {"order" => "desc"}}
else
(klass and klass.respond_to?(:get_sort_by)) ? klass.get_sort_by(sort_by) : nil
end
end
def searchable_models
searchable_types.except(:all).keys.map {|model| model.to_s.classify.constantize}
end
def query_string(expression="", models=[])
return { match_all: {} } if not expression
{
query_string: {
query: "*"+expression.downcase.split.join('* *')+"*",
fields: fields_from_models(models),
tie_breaker: 0.4,
minimum_should_match: "100%"
}
}
end
def query_method(expression="", models=[], categories=[])
query = {}
current_user ||= nil
query[:query] = {
filtered: {
query: query_string(expression, models),
filter: {
bool: {}
}
}
}
query[:query][:filtered][:filter][:bool] = {
should: models.map {|model| model.filter(environment: @environment.id, user: current_user )}
}
unless categories.blank?
query[:query][:filtered][:filter][:bool][:must] = models.first.filter_category(categories)
end
query
end
def get_query(text="", options={})
klass = options[:klass]
sort_by = options[:sort_by]
categories = (options[:categories] || "").split(",")
categories = categories.map(&:to_i)
models = (klass.nil?) ? searchable_models : [klass]
query = query_method(text, models, categories)
query[:sort] = sort_by if sort_by
query
end
def fields_from_models(klasses)
fields = Set.new
klasses.each do |klass|
klass::SEARCHABLE_FIELDS.map do |key, value|
if value and value[:weight]
fields.add "#{key}^#{value[:weight]}"
else
fields.add "#{key}"
end
end
end
fields.to_a
end
end