elasticsearch-persistence-queryable 0.1.8
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +678 -0
- data/Rakefile +57 -0
- data/elasticsearch-persistence.gemspec +57 -0
- data/examples/music/album.rb +34 -0
- data/examples/music/artist.rb +50 -0
- data/examples/music/artists/_form.html.erb +8 -0
- data/examples/music/artists/artists_controller.rb +67 -0
- data/examples/music/artists/artists_controller_test.rb +53 -0
- data/examples/music/artists/index.html.erb +57 -0
- data/examples/music/artists/show.html.erb +51 -0
- data/examples/music/assets/application.css +226 -0
- data/examples/music/assets/autocomplete.css +48 -0
- data/examples/music/assets/blank_cover.png +0 -0
- data/examples/music/assets/form.css +113 -0
- data/examples/music/index_manager.rb +60 -0
- data/examples/music/search/index.html.erb +93 -0
- data/examples/music/search/search_controller.rb +41 -0
- data/examples/music/search/search_controller_test.rb +9 -0
- data/examples/music/search/search_helper.rb +15 -0
- data/examples/music/suggester.rb +45 -0
- data/examples/music/template.rb +392 -0
- data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.css +7 -0
- data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.js +6 -0
- data/examples/notes/.gitignore +7 -0
- data/examples/notes/Gemfile +28 -0
- data/examples/notes/README.markdown +36 -0
- data/examples/notes/application.rb +238 -0
- data/examples/notes/config.ru +7 -0
- data/examples/notes/test.rb +118 -0
- data/lib/elasticsearch/per_thread_registry.rb +53 -0
- data/lib/elasticsearch/persistence/client.rb +51 -0
- data/lib/elasticsearch/persistence/inheritence.rb +9 -0
- data/lib/elasticsearch/persistence/model/base.rb +95 -0
- data/lib/elasticsearch/persistence/model/callbacks.rb +37 -0
- data/lib/elasticsearch/persistence/model/errors.rb +9 -0
- data/lib/elasticsearch/persistence/model/find.rb +155 -0
- data/lib/elasticsearch/persistence/model/gateway_delegation.rb +23 -0
- data/lib/elasticsearch/persistence/model/hash_wrapper.rb +17 -0
- data/lib/elasticsearch/persistence/model/rails.rb +39 -0
- data/lib/elasticsearch/persistence/model/store.rb +271 -0
- data/lib/elasticsearch/persistence/model.rb +148 -0
- data/lib/elasticsearch/persistence/null_relation.rb +56 -0
- data/lib/elasticsearch/persistence/query_cache.rb +68 -0
- data/lib/elasticsearch/persistence/querying.rb +21 -0
- data/lib/elasticsearch/persistence/relation/delegation.rb +130 -0
- data/lib/elasticsearch/persistence/relation/finder_methods.rb +39 -0
- data/lib/elasticsearch/persistence/relation/merger.rb +179 -0
- data/lib/elasticsearch/persistence/relation/query_builder.rb +279 -0
- data/lib/elasticsearch/persistence/relation/query_methods.rb +362 -0
- data/lib/elasticsearch/persistence/relation/search_option_methods.rb +44 -0
- data/lib/elasticsearch/persistence/relation/spawn_methods.rb +61 -0
- data/lib/elasticsearch/persistence/relation.rb +110 -0
- data/lib/elasticsearch/persistence/repository/class.rb +71 -0
- data/lib/elasticsearch/persistence/repository/find.rb +73 -0
- data/lib/elasticsearch/persistence/repository/naming.rb +115 -0
- data/lib/elasticsearch/persistence/repository/response/results.rb +105 -0
- data/lib/elasticsearch/persistence/repository/search.rb +156 -0
- data/lib/elasticsearch/persistence/repository/serialize.rb +31 -0
- data/lib/elasticsearch/persistence/repository/store.rb +94 -0
- data/lib/elasticsearch/persistence/repository.rb +77 -0
- data/lib/elasticsearch/persistence/scoping/default.rb +137 -0
- data/lib/elasticsearch/persistence/scoping/named.rb +70 -0
- data/lib/elasticsearch/persistence/scoping.rb +52 -0
- data/lib/elasticsearch/persistence/version.rb +5 -0
- data/lib/elasticsearch/persistence.rb +157 -0
- data/lib/elasticsearch/rails_compatibility.rb +17 -0
- data/lib/rails/generators/elasticsearch/model/model_generator.rb +21 -0
- data/lib/rails/generators/elasticsearch/model/templates/model.rb.tt +9 -0
- data/lib/rails/generators/elasticsearch_generator.rb +2 -0
- data/lib/rails/instrumentation/railtie.rb +31 -0
- data/lib/rails/instrumentation.rb +10 -0
- data/test/integration/model/model_basic_test.rb +157 -0
- data/test/integration/repository/custom_class_test.rb +85 -0
- data/test/integration/repository/customized_class_test.rb +82 -0
- data/test/integration/repository/default_class_test.rb +114 -0
- data/test/integration/repository/virtus_model_test.rb +114 -0
- data/test/test_helper.rb +53 -0
- data/test/unit/model_base_test.rb +48 -0
- data/test/unit/model_find_test.rb +148 -0
- data/test/unit/model_gateway_test.rb +99 -0
- data/test/unit/model_rails_test.rb +88 -0
- data/test/unit/model_store_test.rb +514 -0
- data/test/unit/persistence_test.rb +32 -0
- data/test/unit/repository_class_test.rb +51 -0
- data/test/unit/repository_client_test.rb +32 -0
- data/test/unit/repository_find_test.rb +388 -0
- data/test/unit/repository_indexing_test.rb +37 -0
- data/test/unit/repository_module_test.rb +146 -0
- data/test/unit/repository_naming_test.rb +146 -0
- data/test/unit/repository_response_results_test.rb +98 -0
- data/test/unit/repository_search_test.rb +117 -0
- data/test/unit/repository_serialize_test.rb +57 -0
- data/test/unit/repository_store_test.rb +303 -0
- metadata +487 -0
@@ -0,0 +1,279 @@
|
|
1
|
+
module Elasticsearch
|
2
|
+
module Persistence
|
3
|
+
class QueryBuilder
|
4
|
+
|
5
|
+
attr_reader :structure, :values
|
6
|
+
|
7
|
+
def initialize(values)
|
8
|
+
@values = values
|
9
|
+
end
|
10
|
+
|
11
|
+
def aggregations
|
12
|
+
values[:aggregation]
|
13
|
+
end
|
14
|
+
|
15
|
+
def filters
|
16
|
+
values[:filter]
|
17
|
+
end
|
18
|
+
|
19
|
+
def or_filters
|
20
|
+
values[:or_filter]
|
21
|
+
end
|
22
|
+
|
23
|
+
def query
|
24
|
+
@query ||= compact_where(values[:where])
|
25
|
+
end
|
26
|
+
|
27
|
+
def query_strings
|
28
|
+
@query_string ||= compact_where(values[:query_string], bool: false)
|
29
|
+
end
|
30
|
+
|
31
|
+
def must_nots
|
32
|
+
@must_nots ||= compact_where(values[:must_not])
|
33
|
+
end
|
34
|
+
|
35
|
+
def shoulds
|
36
|
+
@shoulds ||= compact_where(values[:should])
|
37
|
+
end
|
38
|
+
|
39
|
+
def fields
|
40
|
+
values[:field]
|
41
|
+
end
|
42
|
+
|
43
|
+
def source
|
44
|
+
values[:source]
|
45
|
+
end
|
46
|
+
|
47
|
+
def highlights
|
48
|
+
values[:highlight]
|
49
|
+
end
|
50
|
+
|
51
|
+
def size
|
52
|
+
values[:size]
|
53
|
+
end
|
54
|
+
|
55
|
+
def sort
|
56
|
+
values[:order]
|
57
|
+
end
|
58
|
+
|
59
|
+
def query_filters
|
60
|
+
values[:filter]
|
61
|
+
end
|
62
|
+
|
63
|
+
def search_options
|
64
|
+
build_search_options
|
65
|
+
end
|
66
|
+
|
67
|
+
def query_string_options
|
68
|
+
@query_string_options || {}
|
69
|
+
end
|
70
|
+
|
71
|
+
def count?
|
72
|
+
values[:count]
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_elastic
|
76
|
+
@structure = Jbuilder.new ignore_nil: true
|
77
|
+
build_query
|
78
|
+
build_sort unless sort.blank?
|
79
|
+
build_highlights unless highlights.blank?
|
80
|
+
build_fields unless fields.blank?
|
81
|
+
build_source unless source.blank?
|
82
|
+
build_aggregations unless aggregations.blank?
|
83
|
+
structure.attributes!
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def missing_bool_query?
|
89
|
+
query.nil? && must_nots.nil? && shoulds.nil?
|
90
|
+
end
|
91
|
+
|
92
|
+
def missing_query_string?
|
93
|
+
query_strings.nil?
|
94
|
+
end
|
95
|
+
|
96
|
+
def missing_query_filter?
|
97
|
+
query_filters.nil? && or_filters.nil?
|
98
|
+
end
|
99
|
+
|
100
|
+
def build_query
|
101
|
+
return if missing_bool_query? && missing_query_string? && missing_query_filter?
|
102
|
+
structure.query do
|
103
|
+
structure.bool do
|
104
|
+
structure.must query unless missing_bool_query?
|
105
|
+
structure.must_not must_nots unless must_nots.nil?
|
106
|
+
structure.should shoulds unless shoulds.nil?
|
107
|
+
|
108
|
+
build_filtered_query if query_filters || or_filters
|
109
|
+
|
110
|
+
end unless missing_bool_query? && missing_query_filter?
|
111
|
+
|
112
|
+
|
113
|
+
structure.query_string do
|
114
|
+
structure.extract! query_string_options, *query_string_options.keys
|
115
|
+
structure.query query_strings
|
116
|
+
end unless query_strings.nil?
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def build_filtered_query
|
121
|
+
structure.filter do
|
122
|
+
structure.or do
|
123
|
+
or_filters.each do |f|
|
124
|
+
structure.child! do
|
125
|
+
structure.set! f[:name], extract_filters(f[:name], f[:args])
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end unless or_filters.blank?
|
129
|
+
|
130
|
+
structure.bool do
|
131
|
+
structure.must do
|
132
|
+
query_filters.each do |f|
|
133
|
+
structure.child! do
|
134
|
+
structure.set! f[:name], extract_filters(f[:name], f[:args])
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end unless query_filters.blank?
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def build_source
|
143
|
+
if [true,false].include? source.first
|
144
|
+
structure._source source.first
|
145
|
+
else
|
146
|
+
structure._source do
|
147
|
+
structure.include source.first.delete(:include) if source.first.has_key? :include
|
148
|
+
structure.exclude source.first.delete(:exclude) if source.first.has_key? :exclude
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def build_sort
|
154
|
+
structure.sort sort.flatten.inject(Hash.new) { |h,v| h.merge(v) }
|
155
|
+
end
|
156
|
+
|
157
|
+
def build_highlights
|
158
|
+
structure.highlight do
|
159
|
+
structure.fields do
|
160
|
+
highlights.each do |highlight|
|
161
|
+
structure.set! highlight, extract_highlighter(highlight)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def build_filters
|
168
|
+
filters.each do |f|
|
169
|
+
structure.filter extract_filters(f[:name], f[:args])
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def build_or_filters
|
174
|
+
or_filters.each do |f|
|
175
|
+
structure.filter extract_filters(f[:name], f[:args])
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def build_aggregations
|
180
|
+
structure.aggregations do
|
181
|
+
aggregations.each do |agg|
|
182
|
+
structure.set! agg[:name], aggregation(agg[:name], agg[:args])
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_fields
|
188
|
+
structure.fields do
|
189
|
+
structure.array! fields.flatten
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def build_search_options
|
194
|
+
values[:search_option] ||= []
|
195
|
+
|
196
|
+
opts = extra_search_options
|
197
|
+
(values[:search_option] + [opts]).compact.inject(Hash.new) { |h,k,v| h.merge(k) }
|
198
|
+
end
|
199
|
+
|
200
|
+
def extra_search_options
|
201
|
+
[:size].inject(Hash.new) { |h,k| h[k] = self.send(k) unless self.send(k).nil?; h}
|
202
|
+
end
|
203
|
+
|
204
|
+
def compact_where(q, opts = {bool:true})
|
205
|
+
return if q.nil?
|
206
|
+
if opts.delete(:bool)
|
207
|
+
as_must(q)
|
208
|
+
else
|
209
|
+
as_query_string(q.flatten)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def as_must(q)
|
214
|
+
_must = []
|
215
|
+
q.each do |arg|
|
216
|
+
arg.each_pair { |k,v| _must << (v.is_a?(Array) ? {terms: Hash[k,v]} : {term: Hash[k,v]}) } if arg.class == Hash
|
217
|
+
_must << {term: Hash[[arg.split(/:/).collect(&:strip)]]} if arg.class == String
|
218
|
+
_must << arg.first if arg.class == Array
|
219
|
+
end
|
220
|
+
_must.length == 1 ? _must.first : _must
|
221
|
+
end
|
222
|
+
|
223
|
+
def as_query_string(q)
|
224
|
+
_and = []
|
225
|
+
|
226
|
+
@query_string_options = q.pop if q.length > 1
|
227
|
+
|
228
|
+
q.each do |arg|
|
229
|
+
arg.each_pair { |k,v| _and << "(#{k}:#{v})" } if arg.class == Hash
|
230
|
+
_and << "(#{arg})" if arg.class == String
|
231
|
+
end
|
232
|
+
_and.join(" AND ")
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
def extract_highlighter(highlighter)
|
238
|
+
Jbuilder.new do |highlight|
|
239
|
+
highlight.extract! highlighter
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def extract_filters(name,opts = {})
|
244
|
+
Jbuilder.new do |filter|
|
245
|
+
case
|
246
|
+
when opts.is_a?(Hash)
|
247
|
+
filter.extract! opts, *opts.keys
|
248
|
+
when opts.is_a?(Array)
|
249
|
+
extract_filter_arguments_from_array(filter, opts)
|
250
|
+
else
|
251
|
+
raise "#filter only accepts Hash or Array"
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def aggregation(name, opts = {})
|
257
|
+
Jbuilder.new do |agg|
|
258
|
+
case
|
259
|
+
when opts.is_a?(Hash)
|
260
|
+
agg.extract! opts, *opts.keys
|
261
|
+
when opts.is_a?(Array)
|
262
|
+
extract_filter_arguments_from_array(agg, opts)
|
263
|
+
else
|
264
|
+
raise "#aggregation only accepts Hash or Array"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def extract_filter_arguments_from_array(element, opts)
|
270
|
+
opts.each do |opt|
|
271
|
+
element.child! do
|
272
|
+
element.extract! opt , *opt.keys
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
@@ -0,0 +1,362 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
|
3
|
+
module Elasticsearch
|
4
|
+
module Persistence
|
5
|
+
module QueryMethods
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
|
9
|
+
MULTI_VALUE_METHODS = [:where, :order, :field, :highlight, :source,
|
10
|
+
:must_not, :should, :query_string,
|
11
|
+
:aggregation, :search_option,
|
12
|
+
:filter, :or_filter, :extending, :skip_callbacks]
|
13
|
+
SINGLE_VALUE_METHODS = [:size]
|
14
|
+
|
15
|
+
class WhereChain
|
16
|
+
def initialize(scope)
|
17
|
+
@scope = scope
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
MULTI_VALUE_METHODS.each do |name|
|
23
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
24
|
+
def #{name}_values # def select_values
|
25
|
+
@values[:#{name}] || [] # @values[:select] || []
|
26
|
+
end # end
|
27
|
+
#
|
28
|
+
def #{name}_values=(values) # def select_values=(values)
|
29
|
+
raise ImmutableRelation if @loaded # raise ImmutableRelation if @loaded
|
30
|
+
@values[:#{name}] = values # @values[:select] = values
|
31
|
+
end # end
|
32
|
+
CODE
|
33
|
+
end
|
34
|
+
|
35
|
+
SINGLE_VALUE_METHODS.each do |name|
|
36
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
37
|
+
def #{name}_value # def readonly_value
|
38
|
+
@values[:#{name}] # @values[:readonly]
|
39
|
+
end # end
|
40
|
+
CODE
|
41
|
+
end
|
42
|
+
|
43
|
+
SINGLE_VALUE_METHODS.each do |name|
|
44
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
45
|
+
def #{name}_value=(value) # def readonly_value=(value)
|
46
|
+
raise ImmutableRelation if @loaded # raise ImmutableRelation if @loaded
|
47
|
+
@values[:#{name}] = value # @values[:readonly] = value
|
48
|
+
end # end
|
49
|
+
CODE
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
def order(*args)
|
55
|
+
check_if_method_has_arguments!(:order, args)
|
56
|
+
spawn.order!(*args)
|
57
|
+
end
|
58
|
+
|
59
|
+
def order!(*args)
|
60
|
+
self.order_values += [preprocess_order_args(args)]
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
alias :sort :order
|
65
|
+
|
66
|
+
|
67
|
+
def skip_callbacks(*args)
|
68
|
+
spawn.skip_callbacks!(*args)
|
69
|
+
end
|
70
|
+
|
71
|
+
def skip_callbacks!(*args)
|
72
|
+
self.skip_callbacks_values += args
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
alias :sort :order
|
77
|
+
|
78
|
+
|
79
|
+
def size(args)
|
80
|
+
spawn.size!(args)
|
81
|
+
end
|
82
|
+
|
83
|
+
def size!(args)
|
84
|
+
self.size_value = args
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
alias :limit :size
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
def where(opts = :chain, *rest)
|
94
|
+
if opts == :chain
|
95
|
+
WhereChain.new(spawn)
|
96
|
+
elsif opts.blank?
|
97
|
+
self
|
98
|
+
else
|
99
|
+
spawn.where!(opts, *rest)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
alias :must :where
|
104
|
+
|
105
|
+
def where!(opts, *rest) # :nodoc:
|
106
|
+
if opts == :chain
|
107
|
+
WhereChain.new(self)
|
108
|
+
else
|
109
|
+
#if Hash === opts
|
110
|
+
#opts = sanitize_forbidden_attributes(opts)
|
111
|
+
#end
|
112
|
+
|
113
|
+
self.where_values += build_where(opts, rest)
|
114
|
+
self
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
def query_string(opts = :chain, *rest)
|
122
|
+
if opts == :chain
|
123
|
+
WhereChain.new(spawn)
|
124
|
+
elsif opts.blank?
|
125
|
+
self
|
126
|
+
else
|
127
|
+
spawn.query_string!(opts, *rest)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def query_string!(opts, *rest) # :nodoc:
|
132
|
+
if opts == :chain
|
133
|
+
WhereChain.new(self)
|
134
|
+
else
|
135
|
+
self.query_string_values += build_where(opts, rest)
|
136
|
+
self
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
def must_not(opts = :chain, *rest)
|
144
|
+
if opts == :chain
|
145
|
+
WhereChain.new(spawn)
|
146
|
+
elsif opts.blank?
|
147
|
+
self
|
148
|
+
else
|
149
|
+
spawn.must_not!(opts, *rest)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
alias :where_not :must_not
|
154
|
+
|
155
|
+
def must_not!(opts, *rest)
|
156
|
+
if opts == :chain
|
157
|
+
WhereChain.new(self)
|
158
|
+
else
|
159
|
+
self.must_not_values += build_where(opts, rest)
|
160
|
+
self
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
def should(opts = :chain, *rest)
|
168
|
+
if opts == :chain
|
169
|
+
WhereChain.new(spawn)
|
170
|
+
elsif opts.blank?
|
171
|
+
self
|
172
|
+
else
|
173
|
+
spawn.should!(opts, *rest)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def should!(opts, *rest)
|
178
|
+
if opts == :chain
|
179
|
+
WhereChain.new(self)
|
180
|
+
else
|
181
|
+
self.should_values += build_where(opts, rest)
|
182
|
+
self
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
def or_filter(name, options = {}, &block)
|
188
|
+
spawn.or_filter!(name, options, &block)
|
189
|
+
end
|
190
|
+
|
191
|
+
def or_filter!(name, options = {}, &block)
|
192
|
+
self.or_filter_values += [{name: name, args: options}]
|
193
|
+
self
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
def filter(name, options = {}, &block)
|
199
|
+
spawn.filter!(name, options, &block)
|
200
|
+
end
|
201
|
+
|
202
|
+
def filter!(name, options = {}, &block)
|
203
|
+
self.filter_values += [{name: name, args: options}]
|
204
|
+
self
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
|
209
|
+
|
210
|
+
def aggregation(name, options = {}, &block)
|
211
|
+
spawn.aggregation!(name, options, &block)
|
212
|
+
end
|
213
|
+
|
214
|
+
def aggregation!(name, options = {}, &block)
|
215
|
+
self.aggregation_values += [{name: name, args: options}]
|
216
|
+
self
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
def field(*args)
|
223
|
+
spawn.field!(*args)
|
224
|
+
end
|
225
|
+
alias :fields :field
|
226
|
+
|
227
|
+
def field!(*args)
|
228
|
+
self.field_values += args
|
229
|
+
self
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
def source(*args)
|
236
|
+
spawn.source!(*args)
|
237
|
+
end
|
238
|
+
|
239
|
+
def source!(*args)
|
240
|
+
self.source_values += args
|
241
|
+
self
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
|
246
|
+
|
247
|
+
def has_field?(field)
|
248
|
+
spawn.filter(:exists, {field: field})
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
|
254
|
+
def bind(value)
|
255
|
+
spawn.bind!(value)
|
256
|
+
end
|
257
|
+
|
258
|
+
def bind!(value) # :nodoc:
|
259
|
+
self.bind_values += [value]
|
260
|
+
self
|
261
|
+
end
|
262
|
+
|
263
|
+
def build_where(opts, other = [])
|
264
|
+
case opts
|
265
|
+
when String, Array
|
266
|
+
#TODO: Remove duplication with: /activerecord/lib/active_record/sanitization.rb:113
|
267
|
+
values = Hash === other.first ? other.first.values : other
|
268
|
+
|
269
|
+
values.grep(Elasticsearch::Persistence::Relation) do |rel|
|
270
|
+
self.bind_values += rel.bind_values
|
271
|
+
end
|
272
|
+
|
273
|
+
[other.empty? ? opts : ([opts] + other)]
|
274
|
+
when Hash
|
275
|
+
[other.empty? ? opts : ([opts] + other)]
|
276
|
+
else
|
277
|
+
[opts]
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def highlight(*args)
|
282
|
+
spawn.highlight!(*args)
|
283
|
+
end
|
284
|
+
|
285
|
+
def highlight!(*args)
|
286
|
+
self.highlight_values += args
|
287
|
+
self
|
288
|
+
end
|
289
|
+
|
290
|
+
|
291
|
+
# Returns a chainable relation with zero records.
|
292
|
+
#
|
293
|
+
#
|
294
|
+
def none
|
295
|
+
extending(NullRelation)
|
296
|
+
end
|
297
|
+
|
298
|
+
def none! # :nodoc:
|
299
|
+
extending!(NullRelation)
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
def extending(*modules, &block)
|
304
|
+
if modules.any? || block
|
305
|
+
spawn.extending!(*modules, &block)
|
306
|
+
else
|
307
|
+
self
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def extending!(*modules, &block) # :nodoc:
|
312
|
+
modules << Module.new(&block) if block
|
313
|
+
modules.flatten!
|
314
|
+
|
315
|
+
self.extending_values += modules
|
316
|
+
extend(*extending_values) if extending_values.any?
|
317
|
+
|
318
|
+
self
|
319
|
+
end
|
320
|
+
|
321
|
+
private
|
322
|
+
|
323
|
+
def check_if_method_has_arguments!(method_name, args)
|
324
|
+
if args.blank?
|
325
|
+
raise ArgumentError, "The method .#{method_name}() must contain arguments."
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
VALID_DIRECTIONS = [:asc, :desc, :ASC, :DESC,
|
330
|
+
'asc', 'desc', 'ASC', 'DESC'] # :nodoc:
|
331
|
+
|
332
|
+
def validate_order_args(args)
|
333
|
+
args.each do |arg|
|
334
|
+
next unless arg.is_a?(Hash)
|
335
|
+
arg.each do |_key, value|
|
336
|
+
raise ArgumentError, "Direction \"#{value}\" is invalid. Valid " \
|
337
|
+
"directions are: #{VALID_DIRECTIONS.inspect}" unless VALID_DIRECTIONS.include?(value)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
def preprocess_order_args(order_args)
|
343
|
+
args = order_args.reject{ |arg| arg.is_a?(Hash) }.take(2)
|
344
|
+
return [Hash[[args]]] if args.length == 2
|
345
|
+
order_args.select { |arg| arg.is_a?(Hash)}.flatten
|
346
|
+
end
|
347
|
+
|
348
|
+
def add_relations_to_bind_values(attributes)
|
349
|
+
if attributes.is_a?(Hash)
|
350
|
+
attributes.each_value do |value|
|
351
|
+
if value.is_a?(ActiveRecord::Relation)
|
352
|
+
self.bind_values += value.bind_values
|
353
|
+
else
|
354
|
+
add_relations_to_bind_values(value)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
end
|
362
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Elasticsearch
|
2
|
+
module Persistence
|
3
|
+
|
4
|
+
module SearchOptionMethods
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def routing(args)
|
8
|
+
check_if_method_has_arguments!(:routing, args)
|
9
|
+
spawn.routing!(args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def routing!(args)
|
13
|
+
merge_search_option_values(:routing, args)
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def search_type(args)
|
18
|
+
check_if_method_has_arguments!(:search_type, args)
|
19
|
+
spawn.search_type!(args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def search_type!(args)
|
23
|
+
merge_search_option_values(:search_type, args)
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def search_options(*args)
|
28
|
+
spawn.search_options!(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def search_options!(*args)
|
32
|
+
self.search_option_values += args
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def merge_search_option_values(key, value)
|
39
|
+
self.search_option_values += [Hash[key,value]]
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|