load_balanced_tire 0.1
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/.gitignore +14 -0
- data/.travis.yml +29 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +760 -0
- data/Rakefile +78 -0
- data/examples/rails-application-template.rb +249 -0
- data/examples/tire-dsl.rb +876 -0
- data/lib/tire.rb +55 -0
- data/lib/tire/alias.rb +296 -0
- data/lib/tire/configuration.rb +30 -0
- data/lib/tire/dsl.rb +43 -0
- data/lib/tire/http/client.rb +62 -0
- data/lib/tire/http/clients/curb.rb +61 -0
- data/lib/tire/http/clients/faraday.rb +71 -0
- data/lib/tire/http/response.rb +27 -0
- data/lib/tire/index.rb +361 -0
- data/lib/tire/logger.rb +60 -0
- data/lib/tire/model/callbacks.rb +40 -0
- data/lib/tire/model/import.rb +26 -0
- data/lib/tire/model/indexing.rb +128 -0
- data/lib/tire/model/naming.rb +100 -0
- data/lib/tire/model/percolate.rb +99 -0
- data/lib/tire/model/persistence.rb +71 -0
- data/lib/tire/model/persistence/attributes.rb +143 -0
- data/lib/tire/model/persistence/finders.rb +66 -0
- data/lib/tire/model/persistence/storage.rb +69 -0
- data/lib/tire/model/search.rb +307 -0
- data/lib/tire/results/collection.rb +114 -0
- data/lib/tire/results/item.rb +86 -0
- data/lib/tire/results/pagination.rb +54 -0
- data/lib/tire/rubyext/hash.rb +8 -0
- data/lib/tire/rubyext/ruby_1_8.rb +7 -0
- data/lib/tire/rubyext/symbol.rb +11 -0
- data/lib/tire/search.rb +188 -0
- data/lib/tire/search/facet.rb +74 -0
- data/lib/tire/search/filter.rb +28 -0
- data/lib/tire/search/highlight.rb +37 -0
- data/lib/tire/search/query.rb +186 -0
- data/lib/tire/search/scan.rb +114 -0
- data/lib/tire/search/script_field.rb +23 -0
- data/lib/tire/search/sort.rb +25 -0
- data/lib/tire/tasks.rb +135 -0
- data/lib/tire/utils.rb +17 -0
- data/lib/tire/version.rb +22 -0
- data/test/fixtures/articles/1.json +1 -0
- data/test/fixtures/articles/2.json +1 -0
- data/test/fixtures/articles/3.json +1 -0
- data/test/fixtures/articles/4.json +1 -0
- data/test/fixtures/articles/5.json +1 -0
- data/test/integration/active_model_indexing_test.rb +51 -0
- data/test/integration/active_model_searchable_test.rb +114 -0
- data/test/integration/active_record_searchable_test.rb +446 -0
- data/test/integration/boolean_queries_test.rb +43 -0
- data/test/integration/count_test.rb +34 -0
- data/test/integration/custom_score_queries_test.rb +88 -0
- data/test/integration/dis_max_queries_test.rb +68 -0
- data/test/integration/dsl_search_test.rb +22 -0
- data/test/integration/explanation_test.rb +44 -0
- data/test/integration/facets_test.rb +259 -0
- data/test/integration/filtered_queries_test.rb +66 -0
- data/test/integration/filters_test.rb +63 -0
- data/test/integration/fuzzy_queries_test.rb +20 -0
- data/test/integration/highlight_test.rb +64 -0
- data/test/integration/index_aliases_test.rb +122 -0
- data/test/integration/index_mapping_test.rb +43 -0
- data/test/integration/index_store_test.rb +96 -0
- data/test/integration/index_update_document_test.rb +111 -0
- data/test/integration/mongoid_searchable_test.rb +309 -0
- data/test/integration/percolator_test.rb +111 -0
- data/test/integration/persistent_model_test.rb +130 -0
- data/test/integration/prefix_query_test.rb +43 -0
- data/test/integration/query_return_version_test.rb +70 -0
- data/test/integration/query_string_test.rb +52 -0
- data/test/integration/range_queries_test.rb +36 -0
- data/test/integration/reindex_test.rb +46 -0
- data/test/integration/results_test.rb +39 -0
- data/test/integration/scan_test.rb +56 -0
- data/test/integration/script_fields_test.rb +38 -0
- data/test/integration/sort_test.rb +36 -0
- data/test/integration/text_query_test.rb +39 -0
- data/test/models/active_model_article.rb +31 -0
- data/test/models/active_model_article_with_callbacks.rb +49 -0
- data/test/models/active_model_article_with_custom_document_type.rb +7 -0
- data/test/models/active_model_article_with_custom_index_name.rb +7 -0
- data/test/models/active_record_models.rb +122 -0
- data/test/models/article.rb +15 -0
- data/test/models/mongoid_models.rb +97 -0
- data/test/models/persistent_article.rb +11 -0
- data/test/models/persistent_article_in_namespace.rb +12 -0
- data/test/models/persistent_article_with_casting.rb +28 -0
- data/test/models/persistent_article_with_defaults.rb +11 -0
- data/test/models/persistent_articles_with_custom_index_name.rb +10 -0
- data/test/models/supermodel_article.rb +17 -0
- data/test/models/validated_model.rb +11 -0
- data/test/test_helper.rb +93 -0
- data/test/unit/active_model_lint_test.rb +17 -0
- data/test/unit/configuration_test.rb +74 -0
- data/test/unit/http_client_test.rb +76 -0
- data/test/unit/http_response_test.rb +49 -0
- data/test/unit/index_alias_test.rb +275 -0
- data/test/unit/index_test.rb +894 -0
- data/test/unit/logger_test.rb +125 -0
- data/test/unit/model_callbacks_test.rb +116 -0
- data/test/unit/model_import_test.rb +71 -0
- data/test/unit/model_persistence_test.rb +528 -0
- data/test/unit/model_search_test.rb +913 -0
- data/test/unit/results_collection_test.rb +281 -0
- data/test/unit/results_item_test.rb +162 -0
- data/test/unit/rubyext_test.rb +66 -0
- data/test/unit/search_facet_test.rb +153 -0
- data/test/unit/search_filter_test.rb +42 -0
- data/test/unit/search_highlight_test.rb +46 -0
- data/test/unit/search_query_test.rb +301 -0
- data/test/unit/search_scan_test.rb +113 -0
- data/test/unit/search_script_field_test.rb +26 -0
- data/test/unit/search_sort_test.rb +50 -0
- data/test/unit/search_test.rb +499 -0
- data/test/unit/tire_test.rb +126 -0
- data/tire.gemspec +90 -0
- metadata +549 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
module Tire
|
2
|
+
module Search
|
3
|
+
|
4
|
+
#--
|
5
|
+
# TODO: Implement all elastic search facets (geo, histogram, range, etc)
|
6
|
+
# http://elasticsearch.org/guide/reference/api/search/facets/
|
7
|
+
#++
|
8
|
+
|
9
|
+
class Facet
|
10
|
+
|
11
|
+
def initialize(name, options={}, &block)
|
12
|
+
@name = name
|
13
|
+
@options = options
|
14
|
+
block.arity < 1 ? self.instance_eval(&block) : block.call(self) if block_given?
|
15
|
+
end
|
16
|
+
|
17
|
+
def terms(field, options={})
|
18
|
+
size = options.delete(:size) || 10
|
19
|
+
all_terms = options.delete(:all_terms) || false
|
20
|
+
@value = if field.is_a?(Enumerable) and not field.is_a?(String)
|
21
|
+
{ :terms => { :fields => field }.update({ :size => size, :all_terms => all_terms }).update(options) }
|
22
|
+
else
|
23
|
+
{ :terms => { :field => field }.update({ :size => size, :all_terms => all_terms }).update(options) }
|
24
|
+
end
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def date(field, options={})
|
29
|
+
interval = options.delete(:interval) || 'day'
|
30
|
+
@value = { :date_histogram => { :field => field, :interval => interval }.update(options) }
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def range(field, ranges=[], options={})
|
35
|
+
@value = { :range => { :field => field, :ranges => ranges }.update(options) }
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def histogram(field, options={})
|
40
|
+
@value = { :histogram => (options.delete(:histogram) || {:field => field}.update(options)) }
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def statistical(field, options={})
|
45
|
+
@value = { :statistical => (options.delete(:statistical) || {:field => field}.update(options)) }
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def terms_stats(key_field, value_field, options={})
|
50
|
+
@value = { :terms_stats => {:key_field => key_field, :value_field => value_field}.update(options) }
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def query(&block)
|
55
|
+
@value = { :query => Query.new(&block).to_hash }
|
56
|
+
end
|
57
|
+
|
58
|
+
def filter(field, value, options={})
|
59
|
+
@value = { :filter => { :term => { field => value }}.update(options) }
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_json
|
64
|
+
to_hash.to_json
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_hash
|
68
|
+
@value.update @options
|
69
|
+
{ @name => @value }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Tire
|
2
|
+
module Search
|
3
|
+
|
4
|
+
# http://www.elasticsearch.org/guide/reference/api/search/filter.html
|
5
|
+
# http://www.elasticsearch.org/guide/reference/query-dsl/
|
6
|
+
#
|
7
|
+
class Filter
|
8
|
+
|
9
|
+
def initialize(type, *options)
|
10
|
+
value = if options.size < 2
|
11
|
+
options.first || {}
|
12
|
+
else
|
13
|
+
options # An +or+ filter encodes multiple filters as an array
|
14
|
+
end
|
15
|
+
@hash = { type => value }
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json
|
19
|
+
to_hash.to_json
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_hash
|
23
|
+
@hash
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Tire
|
2
|
+
module Search
|
3
|
+
|
4
|
+
# http://www.elasticsearch.org/guide/reference/api/search/highlighting.html
|
5
|
+
#
|
6
|
+
class Highlight
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
@options = (args.last.is_a?(Hash) && args.last.delete(:options)) || {}
|
10
|
+
extract_highlight_tags
|
11
|
+
@fields = args.inject({}) do |result, field|
|
12
|
+
field.is_a?(Hash) ? result.update(field) : result[field.to_sym] = {}; result
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_json
|
17
|
+
to_hash.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_hash
|
21
|
+
{ :fields => @fields }.update @options
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def extract_highlight_tags
|
27
|
+
if tag = @options.delete(:tag)
|
28
|
+
@options.update \
|
29
|
+
:pre_tags => [tag],
|
30
|
+
:post_tags => [tag.to_s.gsub(/^<([a-z]+).*/, '</\1>')]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
module Tire
|
2
|
+
module Search
|
3
|
+
|
4
|
+
class Query
|
5
|
+
def initialize(&block)
|
6
|
+
@value = {}
|
7
|
+
block.arity < 1 ? self.instance_eval(&block) : block.call(self) if block_given?
|
8
|
+
end
|
9
|
+
|
10
|
+
def term(field, value, options={})
|
11
|
+
query = { field => { :term => value }.update(options) }
|
12
|
+
@value = { :term => query }
|
13
|
+
end
|
14
|
+
|
15
|
+
def terms(field, value, options={})
|
16
|
+
@value = { :terms => { field => value } }
|
17
|
+
@value[:terms].update( { :minimum_match => options[:minimum_match] } ) if options[:minimum_match]
|
18
|
+
@value
|
19
|
+
end
|
20
|
+
|
21
|
+
def range(field, value)
|
22
|
+
@value = { :range => { field => value } }
|
23
|
+
end
|
24
|
+
|
25
|
+
def text(field, value, options={})
|
26
|
+
query_options = { :query => value }.update(options)
|
27
|
+
@value = { :text => { field => query_options } }
|
28
|
+
@value
|
29
|
+
end
|
30
|
+
|
31
|
+
def string(value, options={})
|
32
|
+
@value = { :query_string => { :query => value } }
|
33
|
+
@value[:query_string].update(options)
|
34
|
+
@value
|
35
|
+
end
|
36
|
+
|
37
|
+
def prefix(field, value, options={})
|
38
|
+
if options[:boost]
|
39
|
+
@value = { :prefix => { field => { :prefix => value, :boost => options[:boost] } } }
|
40
|
+
else
|
41
|
+
@value = { :prefix => { field => value } }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def custom_score(options={}, &block)
|
46
|
+
@custom_score ||= Query.new(&block)
|
47
|
+
@value[:custom_score] = options
|
48
|
+
@value[:custom_score].update({:query => @custom_score.to_hash})
|
49
|
+
@value
|
50
|
+
end
|
51
|
+
|
52
|
+
def fuzzy(field, value, options={})
|
53
|
+
query = { field => { :term => value }.update(options) }
|
54
|
+
@value = { :fuzzy => query }
|
55
|
+
end
|
56
|
+
|
57
|
+
def boolean(options={}, &block)
|
58
|
+
@boolean ||= BooleanQuery.new(options)
|
59
|
+
block.arity < 1 ? @boolean.instance_eval(&block) : block.call(@boolean) if block_given?
|
60
|
+
@value[:bool] = @boolean.to_hash
|
61
|
+
@value
|
62
|
+
end
|
63
|
+
|
64
|
+
def filtered(&block)
|
65
|
+
@filtered = FilteredQuery.new
|
66
|
+
block.arity < 1 ? @filtered.instance_eval(&block) : block.call(@filtered) if block_given?
|
67
|
+
@value[:filtered] = @filtered.to_hash
|
68
|
+
@value
|
69
|
+
end
|
70
|
+
|
71
|
+
def dis_max(options={}, &block)
|
72
|
+
@dis_max ||= DisMaxQuery.new(options)
|
73
|
+
block.arity < 1 ? @dis_max.instance_eval(&block) : block.call(@dis_max) if block_given?
|
74
|
+
@value[:dis_max] = @dis_max.to_hash
|
75
|
+
@value
|
76
|
+
end
|
77
|
+
|
78
|
+
def all
|
79
|
+
@value = { :match_all => {} }
|
80
|
+
@value
|
81
|
+
end
|
82
|
+
|
83
|
+
def ids(values, type)
|
84
|
+
@value = { :ids => { :values => values, :type => type } }
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_hash
|
88
|
+
@value
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_json
|
92
|
+
to_hash.to_json
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
class BooleanQuery
|
98
|
+
|
99
|
+
# TODO: Try to get rid of multiple `should`, `must`, etc invocations, and wrap queries directly:
|
100
|
+
#
|
101
|
+
# boolean do
|
102
|
+
# should do
|
103
|
+
# string 'foo'
|
104
|
+
# string 'bar'
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# Inherit from Query, implement `encode` method there, and overload it here, so it puts
|
109
|
+
# queries in an Array instead of hash.
|
110
|
+
|
111
|
+
def initialize(options={}, &block)
|
112
|
+
@options = options
|
113
|
+
@value = {}
|
114
|
+
block.arity < 1 ? self.instance_eval(&block) : block.call(self) if block_given?
|
115
|
+
end
|
116
|
+
|
117
|
+
def must(&block)
|
118
|
+
(@value[:must] ||= []) << Query.new(&block).to_hash
|
119
|
+
@value
|
120
|
+
end
|
121
|
+
|
122
|
+
def must_not(&block)
|
123
|
+
(@value[:must_not] ||= []) << Query.new(&block).to_hash
|
124
|
+
@value
|
125
|
+
end
|
126
|
+
|
127
|
+
def should(&block)
|
128
|
+
(@value[:should] ||= []) << Query.new(&block).to_hash
|
129
|
+
@value
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_hash
|
133
|
+
@value.update(@options)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class FilteredQuery
|
138
|
+
def initialize(&block)
|
139
|
+
@value = {}
|
140
|
+
block.arity < 1 ? self.instance_eval(&block) : block.call(self) if block_given?
|
141
|
+
end
|
142
|
+
|
143
|
+
def query(options={}, &block)
|
144
|
+
@value[:query] = Query.new(&block).to_hash
|
145
|
+
@value
|
146
|
+
end
|
147
|
+
|
148
|
+
def filter(type, *options)
|
149
|
+
@value[:filter] ||= {}
|
150
|
+
@value[:filter][:and] ||= []
|
151
|
+
@value[:filter][:and] << Filter.new(type, *options).to_hash
|
152
|
+
@value
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_hash
|
156
|
+
@value
|
157
|
+
end
|
158
|
+
|
159
|
+
def to_json
|
160
|
+
to_hash.to_json
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class DisMaxQuery
|
165
|
+
def initialize(options={}, &block)
|
166
|
+
@options = options
|
167
|
+
@value = {}
|
168
|
+
block.arity < 1 ? self.instance_eval(&block) : block.call(self) if block_given?
|
169
|
+
end
|
170
|
+
|
171
|
+
def query(&block)
|
172
|
+
(@value[:queries] ||= []) << Query.new(&block).to_hash
|
173
|
+
@value
|
174
|
+
end
|
175
|
+
|
176
|
+
def to_hash
|
177
|
+
@value.update(@options)
|
178
|
+
end
|
179
|
+
|
180
|
+
def to_json
|
181
|
+
to_hash.to_json
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Tire
|
2
|
+
module Search
|
3
|
+
|
4
|
+
|
5
|
+
# Performs a "scan/scroll" search request, which obtains a `scroll_id`
|
6
|
+
# and keeps returning documents matching the passed query (or all documents) in batches.
|
7
|
+
#
|
8
|
+
# You may want to iterate over the batches being returned:
|
9
|
+
#
|
10
|
+
# search = Tire::Search::Scan.new('articles')
|
11
|
+
# search.each do |results|
|
12
|
+
# puts results.map(&:title)
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# The scan object has a fully Enumerable-compatible interface, so you may
|
16
|
+
# call methods like `map` or `each_with_index` on it.
|
17
|
+
#
|
18
|
+
# To iterate over individual documents, use the `each_document` method:
|
19
|
+
#
|
20
|
+
# search.each_document do |document|
|
21
|
+
# puts document.title
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# You may limit the result set being returned by a regular Tire DSL query
|
25
|
+
# (or a hash, if you prefer), passed as a second argument:
|
26
|
+
#
|
27
|
+
# search = Tire::Search::Scan.new('articles') do
|
28
|
+
# query { term 'author.exact', 'John Smith' }
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# The feature is also exposed in the Tire top-level DSL:
|
32
|
+
#
|
33
|
+
# search = Tire.scan 'articles' do
|
34
|
+
# query { term 'author.exact', 'John Smith' }
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# See ElasticSearch documentation for further reference:
|
38
|
+
#
|
39
|
+
# * http://www.elasticsearch.org/guide/reference/api/search/search-type.html
|
40
|
+
# * http://www.elasticsearch.org/guide/reference/api/search/scroll.html
|
41
|
+
#
|
42
|
+
class Scan
|
43
|
+
include Enumerable
|
44
|
+
|
45
|
+
attr_reader :indices, :options, :search
|
46
|
+
|
47
|
+
def initialize(indices=nil, options={}, &block)
|
48
|
+
@indices = Array(indices)
|
49
|
+
@options = options.update(:search_type => 'scan', :scroll => '10m')
|
50
|
+
@seen = 0
|
51
|
+
@search = Search.new(@indices, @options, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def url; Configuration.url + "/_search/scroll"; end
|
55
|
+
def params; @options.empty? ? '' : '?' + @options.to_param; end
|
56
|
+
def results; @results || (__perform; @results); end
|
57
|
+
def response; @response || (__perform; @response); end
|
58
|
+
def json; @json || (__perform; @json); end
|
59
|
+
def total; @total || (__perform; @total); end
|
60
|
+
def seen; @seen || (__perform; @seen); end
|
61
|
+
|
62
|
+
def scroll_id
|
63
|
+
@scroll_id ||= @search.perform.json['_scroll_id']
|
64
|
+
end
|
65
|
+
|
66
|
+
def each
|
67
|
+
until results.empty?
|
68
|
+
yield results.results
|
69
|
+
__perform
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def each_document
|
74
|
+
until results.empty?
|
75
|
+
results.each { |item| yield item }
|
76
|
+
__perform
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def size
|
81
|
+
results.size
|
82
|
+
end
|
83
|
+
|
84
|
+
def __perform
|
85
|
+
@response = Configuration.client.get [url, params].join, scroll_id
|
86
|
+
@json = MultiJson.decode @response.body
|
87
|
+
@results = Results::Collection.new @json, @options
|
88
|
+
@total = @json['hits']['total'].to_i
|
89
|
+
@seen += @results.size
|
90
|
+
@scroll_id = @json['_scroll_id']
|
91
|
+
return self
|
92
|
+
ensure
|
93
|
+
__logged
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_a; results; end; alias :to_ary :to_a
|
97
|
+
def to_curl; %Q|curl -X GET "#{url}?pretty=true" -d '#{@scroll_id}'|; end
|
98
|
+
|
99
|
+
def __logged(error=nil)
|
100
|
+
if Configuration.logger
|
101
|
+
Configuration.logger.log_request 'scroll', nil, to_curl
|
102
|
+
|
103
|
+
took = @json['took'] rescue nil
|
104
|
+
code = @response.code rescue nil
|
105
|
+
body = "#{@seen}/#{@total} (#{@seen/@total.to_f*100}%)" rescue nil
|
106
|
+
|
107
|
+
Configuration.logger.log_response code || 'N/A', took || 'N/A', body
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tire
|
2
|
+
module Search
|
3
|
+
|
4
|
+
# http://www.elasticsearch.org/guide/reference/api/search/script-fields.html
|
5
|
+
# http://www.elasticsearch.org/guide/reference/modules/scripting.html
|
6
|
+
|
7
|
+
class ScriptField
|
8
|
+
|
9
|
+
def initialize(name, options)
|
10
|
+
@hash = { name => options }
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_json
|
14
|
+
to_hash.to_json
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_hash
|
18
|
+
@hash
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|