elastictastic 0.5.0 → 0.10.2
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/LICENSE +1 -1
- data/README.md +161 -10
- data/lib/elastictastic/adapter.rb +84 -0
- data/lib/elastictastic/association.rb +6 -0
- data/lib/elastictastic/basic_document.rb +213 -0
- data/lib/elastictastic/bulk_persistence_strategy.rb +64 -19
- data/lib/elastictastic/callbacks.rb +18 -12
- data/lib/elastictastic/child_collection_proxy.rb +15 -11
- data/lib/elastictastic/client.rb +47 -24
- data/lib/elastictastic/configuration.rb +59 -4
- data/lib/elastictastic/dirty.rb +43 -28
- data/lib/elastictastic/discrete_persistence_strategy.rb +48 -23
- data/lib/elastictastic/document.rb +1 -85
- data/lib/elastictastic/embedded_document.rb +34 -0
- data/lib/elastictastic/errors.rb +17 -5
- data/lib/elastictastic/field.rb +3 -0
- data/lib/elastictastic/mass_assignment_security.rb +2 -4
- data/lib/elastictastic/middleware.rb +66 -84
- data/lib/elastictastic/multi_get.rb +30 -0
- data/lib/elastictastic/multi_search.rb +70 -0
- data/lib/elastictastic/nested_document.rb +3 -27
- data/lib/elastictastic/new_relic_instrumentation.rb +8 -8
- data/lib/elastictastic/observing.rb +8 -6
- data/lib/elastictastic/optimistic_locking.rb +57 -0
- data/lib/elastictastic/parent_child.rb +56 -54
- data/lib/elastictastic/persistence.rb +16 -16
- data/lib/elastictastic/properties.rb +136 -96
- data/lib/elastictastic/railtie.rb +1 -1
- data/lib/elastictastic/rotor.rb +105 -0
- data/lib/elastictastic/scope.rb +186 -56
- data/lib/elastictastic/server_error.rb +20 -1
- data/lib/elastictastic/test_helpers.rb +152 -97
- data/lib/elastictastic/thrift/constants.rb +12 -0
- data/lib/elastictastic/thrift/rest.rb +83 -0
- data/lib/elastictastic/thrift/types.rb +124 -0
- data/lib/elastictastic/thrift_adapter.rb +61 -0
- data/lib/elastictastic/transport_methods.rb +27 -0
- data/lib/elastictastic/validations.rb +11 -13
- data/lib/elastictastic/version.rb +1 -1
- data/lib/elastictastic.rb +148 -27
- data/spec/environment.rb +1 -1
- data/spec/examples/bulk_persistence_strategy_spec.rb +151 -23
- data/spec/examples/callbacks_spec.rb +65 -34
- data/spec/examples/dirty_spec.rb +160 -1
- data/spec/examples/document_spec.rb +168 -106
- data/spec/examples/middleware_spec.rb +1 -61
- data/spec/examples/multi_get_spec.rb +127 -0
- data/spec/examples/multi_search_spec.rb +113 -0
- data/spec/examples/observing_spec.rb +24 -3
- data/spec/examples/optimistic_locking_spec.rb +417 -0
- data/spec/examples/parent_child_spec.rb +73 -33
- data/spec/examples/properties_spec.rb +53 -0
- data/spec/examples/rotor_spec.rb +132 -0
- data/spec/examples/scope_spec.rb +78 -18
- data/spec/examples/search_spec.rb +26 -0
- data/spec/examples/validation_spec.rb +7 -1
- data/spec/models/author.rb +1 -1
- data/spec/models/blog.rb +2 -0
- data/spec/models/comment.rb +1 -1
- data/spec/models/photo.rb +9 -0
- data/spec/models/post.rb +3 -0
- metadata +97 -78
- data/lib/elastictastic/resource.rb +0 -4
- data/spec/examples/active_model_lint_spec.rb +0 -20
@@ -9,21 +9,27 @@ module Elastictastic
|
|
9
9
|
define_model_callbacks(*HOOKS)
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
12
|
+
def save(options = {})
|
13
|
+
with_callbacks(:save, options) { super }
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def create(options = {})
|
17
|
+
with_callbacks(:create, options) { super }
|
18
|
+
end
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
def update(options = {})
|
21
|
+
with_callbacks(:update, options) { super }
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy(options = {})
|
25
|
+
with_callbacks(:destroy, options) { super }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
24
29
|
|
25
|
-
|
26
|
-
|
30
|
+
def with_callbacks(name, options)
|
31
|
+
if options[:callbacks] == false then yield
|
32
|
+
else run_callbacks(name) { yield }
|
27
33
|
end
|
28
34
|
end
|
29
35
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Elastictastic
|
2
2
|
class ChildCollectionProxy < Scope
|
3
|
-
attr_reader :parent
|
3
|
+
attr_reader :parent
|
4
4
|
|
5
5
|
def initialize(association, parent)
|
6
6
|
super(
|
@@ -12,10 +12,10 @@ module Elastictastic
|
|
12
12
|
'filter' => { 'term' => { '_parent' => parent.id }}
|
13
13
|
}
|
14
14
|
}
|
15
|
-
)
|
15
|
+
),
|
16
|
+
self
|
16
17
|
)
|
17
18
|
@parent = parent
|
18
|
-
@parent_collection = self
|
19
19
|
@transient_children = []
|
20
20
|
end
|
21
21
|
|
@@ -25,28 +25,32 @@ module Elastictastic
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def first
|
28
|
-
super ||
|
28
|
+
super || transient_children.first
|
29
29
|
end
|
30
30
|
|
31
31
|
def each(&block)
|
32
32
|
if block
|
33
|
-
super
|
34
|
-
|
33
|
+
super if @parent.persisted?
|
34
|
+
transient_children.each(&block)
|
35
35
|
else
|
36
36
|
::Enumerator.new(self, :each)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def persisted!(child)
|
41
|
-
@transient_children.delete(child)
|
42
|
-
end
|
43
|
-
|
44
40
|
def <<(child)
|
45
|
-
child.
|
41
|
+
child.parent = @parent
|
46
42
|
@transient_children << child
|
47
43
|
self
|
48
44
|
end
|
49
45
|
|
46
|
+
def transient_children
|
47
|
+
@transient_children.tap do |children|
|
48
|
+
children.reject! do |child|
|
49
|
+
!child.transient?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
50
54
|
private
|
51
55
|
|
52
56
|
def params_for_find
|
data/lib/elastictastic/client.rb
CHANGED
@@ -1,48 +1,70 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
|
3
1
|
module Elastictastic
|
4
2
|
class Client
|
5
3
|
attr_reader :connection
|
6
4
|
|
7
5
|
def initialize(config)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
if config.logger
|
13
|
-
builder.use Middleware::LogRequests, config.logger
|
14
|
-
end
|
15
|
-
end
|
6
|
+
adapter_options = {
|
7
|
+
:request_timeout => config.request_timeout,
|
8
|
+
:connect_timeout => config.connect_timeout
|
9
|
+
}
|
16
10
|
if config.hosts.length == 1
|
17
|
-
|
18
|
-
|
19
|
-
Faraday.new(:url => config.hosts.first, :builder => builder)
|
11
|
+
connection = Adapter[config.adapter].
|
12
|
+
new(config.hosts.first, adapter_options)
|
20
13
|
else
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
connection = Rotor.new(
|
15
|
+
config.hosts,
|
16
|
+
adapter_options.merge(
|
17
|
+
:adapter => config.adapter,
|
18
|
+
:backoff_threshold => config.backoff_threshold,
|
19
|
+
:backoff_start => config.backoff_start,
|
20
|
+
:backoff_max => config.backoff_max
|
21
|
+
)
|
22
|
+
)
|
24
23
|
end
|
24
|
+
if config.logger
|
25
|
+
connection = Middleware::LogRequests.new(connection, config.logger)
|
26
|
+
end
|
27
|
+
connection = Middleware::JsonDecodeResponse.new(connection)
|
28
|
+
connection = Middleware::JsonEncodeBody.new(connection)
|
29
|
+
connection = Middleware::RaiseServerErrors.new(connection)
|
30
|
+
@connection = connection
|
25
31
|
end
|
26
32
|
|
27
33
|
def create(index, type, id, doc, params = {})
|
28
34
|
if id
|
29
35
|
@connection.put(
|
30
|
-
path_with_query("/#{index}/#{type}/#{id}/_create", params),
|
36
|
+
path_with_query("/#{index}/#{type}/#{id}/_create", params),
|
37
|
+
doc
|
38
|
+
)
|
31
39
|
else
|
32
|
-
@connection.post(
|
40
|
+
@connection.post(
|
41
|
+
path_with_query("/#{index}/#{type}", params),
|
42
|
+
doc
|
43
|
+
)
|
33
44
|
end.body
|
34
45
|
end
|
35
46
|
|
36
47
|
def update(index, type, id, doc, params = {})
|
37
|
-
@connection.put(
|
48
|
+
@connection.put(
|
49
|
+
path_with_query("/#{index}/#{type}/#{id}", params),
|
50
|
+
doc
|
51
|
+
).body
|
38
52
|
end
|
39
53
|
|
40
54
|
def bulk(commands, params = {})
|
41
55
|
@connection.post(path_with_query('/_bulk', params), commands).body
|
42
56
|
end
|
43
57
|
|
58
|
+
def exists?(index, type, id, params = {})
|
59
|
+
@connection.head(
|
60
|
+
path_with_query("/#{index}/#{type}/#{id}", params)
|
61
|
+
).status == 200
|
62
|
+
end
|
63
|
+
|
44
64
|
def get(index, type, id, params = {})
|
45
|
-
@connection.get(
|
65
|
+
@connection.get(
|
66
|
+
path_with_query("/#{index}/#{type}/#{id}", params)
|
67
|
+
).body
|
46
68
|
end
|
47
69
|
|
48
70
|
def mget(docspec, index = nil, type = nil)
|
@@ -67,11 +89,12 @@ module Elastictastic
|
|
67
89
|
).body
|
68
90
|
end
|
69
91
|
|
92
|
+
def msearch(search_bodies)
|
93
|
+
@connection.post('/_msearch', search_bodies).body
|
94
|
+
end
|
95
|
+
|
70
96
|
def scroll(id, options = {})
|
71
|
-
@connection.post(
|
72
|
-
"/_search/scroll?#{options.to_query}",
|
73
|
-
id
|
74
|
-
).body
|
97
|
+
@connection.post("/_search/scroll?#{options.to_query}", id).body
|
75
98
|
end
|
76
99
|
|
77
100
|
def put_mapping(index, type, mapping)
|
@@ -1,15 +1,20 @@
|
|
1
1
|
module Elastictastic
|
2
2
|
class Configuration
|
3
3
|
|
4
|
-
attr_writer :hosts, :
|
5
|
-
attr_accessor :logger
|
4
|
+
attr_writer :hosts, :default_index, :auto_refresh, :default_batch_size, :adapter
|
5
|
+
attr_accessor :logger, :connect_timeout, :request_timeout, :backoff_threshold, :backoff_start, :backoff_max
|
6
|
+
attr_reader :extra_middlewares
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@extra_middlewares = []
|
10
|
+
end
|
6
11
|
|
7
12
|
def host=(host)
|
8
13
|
@hosts = [host]
|
9
14
|
end
|
10
15
|
|
11
16
|
def hosts
|
12
|
-
@hosts ||= [
|
17
|
+
@hosts ||= [default_host]
|
13
18
|
end
|
14
19
|
|
15
20
|
def adapter
|
@@ -17,7 +22,12 @@ module Elastictastic
|
|
17
22
|
end
|
18
23
|
|
19
24
|
def default_index
|
20
|
-
@default_index
|
25
|
+
return @default_index if defined? @default_index
|
26
|
+
if url_from_env && url_from_env.path =~ /^\/([^\/]+)/
|
27
|
+
@default_index = $1
|
28
|
+
else
|
29
|
+
@default_index = 'default'
|
30
|
+
end
|
21
31
|
end
|
22
32
|
|
23
33
|
def auto_refresh
|
@@ -28,6 +38,51 @@ module Elastictastic
|
|
28
38
|
@default_batch_size ||= 100
|
29
39
|
end
|
30
40
|
|
41
|
+
def json_engine=(json_engine)
|
42
|
+
original_engine = MultiJson.engine
|
43
|
+
MultiJson.engine = json_engine
|
44
|
+
@json_engine = MultiJson.engine
|
45
|
+
ensure
|
46
|
+
MultiJson.engine = original_engine
|
47
|
+
end
|
48
|
+
|
49
|
+
def json_engine
|
50
|
+
@json_engine || MultiJson.engine
|
51
|
+
end
|
52
|
+
|
53
|
+
def use_middleware(*args)
|
54
|
+
@extra_middlewares << args
|
55
|
+
end
|
56
|
+
|
57
|
+
def presets
|
58
|
+
@presets ||= ActiveSupport::HashWithIndifferentAccess.new
|
59
|
+
end
|
60
|
+
|
61
|
+
def presets=(new_presets)
|
62
|
+
presets.merge!(new_presets)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def default_host
|
68
|
+
if url_from_env
|
69
|
+
url_from_env.class.build(
|
70
|
+
:host => url_from_env.host,
|
71
|
+
:port => url_from_env.port
|
72
|
+
)
|
73
|
+
else
|
74
|
+
'http://localhost:9200'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def url_from_env
|
79
|
+
return @url_from_env if defined? @url_from_env
|
80
|
+
@url_from_env =
|
81
|
+
if ENV['ELASTICSEARCH_URL']
|
82
|
+
URI.parse(ENV['ELASTICSEARCH_URL'])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
31
86
|
ActiveModel::Observing::ClassMethods.public_instance_methods(false).each do |method|
|
32
87
|
delegate method, :to => :"::Elastictastic::Observing"
|
33
88
|
end
|
data/lib/elastictastic/dirty.rb
CHANGED
@@ -50,54 +50,68 @@ module Elastictastic
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
super
|
57
|
-
end
|
53
|
+
def write_attribute(field, value)
|
54
|
+
attribute_may_change!(field) { super }
|
55
|
+
end
|
58
56
|
|
59
|
-
|
60
|
-
|
57
|
+
def write_embed(field, value)
|
58
|
+
attribute_may_change!(field) do
|
61
59
|
if Array === value
|
62
60
|
value.each do |el|
|
63
61
|
el.nesting_document = self
|
64
62
|
el.nesting_association = field
|
65
63
|
end
|
66
64
|
super(field, NestedCollectionProxy.new(self, field, value))
|
67
|
-
|
65
|
+
elsif value
|
68
66
|
value.nesting_document = self
|
69
67
|
value.nesting_association = field
|
70
68
|
super
|
69
|
+
else
|
70
|
+
super
|
71
71
|
end
|
72
72
|
end
|
73
|
+
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
75
|
+
def save(options = {})
|
76
|
+
super
|
77
|
+
clean_attributes!
|
78
|
+
end
|
78
79
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
80
|
+
def elasticsearch_doc=(doc)
|
81
|
+
super
|
82
|
+
clean_attributes!
|
83
|
+
end
|
83
84
|
|
84
|
-
|
85
|
+
protected
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
87
|
+
def clean_attributes!
|
88
|
+
changed_attributes.clear
|
89
|
+
@_embeds.each_pair do |name, embedded|
|
90
|
+
Util.call_or_map(embedded) { |doc| doc && doc.clean_attributes! }
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
|
94
|
+
def attribute_may_change!(field)
|
95
|
+
attribute_will_change!(field) unless changed_attributes.key?(field)
|
96
|
+
old_value = changed_attributes[field]
|
97
|
+
yield
|
98
|
+
attribute_not_changed!(field) if old_value == __send__(field)
|
99
|
+
end
|
100
|
+
|
101
|
+
def attribute_not_changed!(field)
|
102
|
+
changed_attributes.delete(field)
|
103
|
+
end
|
104
|
+
|
105
|
+
module EmbeddedDocumentMethods
|
95
106
|
attr_writer :nesting_document, :nesting_association
|
96
107
|
|
97
|
-
def
|
98
|
-
super
|
108
|
+
def attribute_may_change!(field)
|
99
109
|
if @nesting_document
|
100
|
-
@nesting_document.
|
110
|
+
@nesting_document.attribute_may_change!(@nesting_association) do
|
111
|
+
super
|
112
|
+
end
|
113
|
+
else
|
114
|
+
super
|
101
115
|
end
|
102
116
|
end
|
103
117
|
end
|
@@ -116,8 +130,9 @@ module Elastictastic
|
|
116
130
|
].each do |destructive_method|
|
117
131
|
module_eval <<-RUBY, __FILE__, __LINE__+1
|
118
132
|
def #{destructive_method}(*args)
|
119
|
-
@owner.__send__(
|
120
|
-
|
133
|
+
@owner.__send__(:attribute_may_change!, @embed_name) do
|
134
|
+
super
|
135
|
+
end
|
121
136
|
end
|
122
137
|
RUBY
|
123
138
|
end
|
@@ -4,39 +4,61 @@ module Elastictastic
|
|
4
4
|
class DiscretePersistenceStrategy
|
5
5
|
include Singleton
|
6
6
|
|
7
|
+
DEFAULT_HANDLER = proc { |e| raise(e) if e }
|
8
|
+
|
7
9
|
attr_accessor :auto_refresh
|
8
10
|
|
9
|
-
def create(doc)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
def create(doc, &block)
|
12
|
+
block ||= DEFAULT_HANDLER
|
13
|
+
begin
|
14
|
+
response = Elastictastic.client.create(
|
15
|
+
doc.index,
|
16
|
+
doc.class.type,
|
17
|
+
doc.id,
|
18
|
+
doc.elasticsearch_doc,
|
19
|
+
params_for(doc)
|
20
|
+
)
|
21
|
+
rescue => e
|
22
|
+
return block.call(e)
|
23
|
+
end
|
17
24
|
doc.id = response['_id']
|
25
|
+
doc.version = response['_version']
|
18
26
|
doc.persisted!
|
27
|
+
block.call
|
19
28
|
end
|
20
29
|
|
21
|
-
def update(doc)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
def update(doc, &block)
|
31
|
+
block ||= DEFAULT_HANDLER
|
32
|
+
begin
|
33
|
+
response = Elastictastic.client.update(
|
34
|
+
doc.index,
|
35
|
+
doc.class.type,
|
36
|
+
doc.id,
|
37
|
+
doc.elasticsearch_doc,
|
38
|
+
params_for(doc)
|
39
|
+
)
|
40
|
+
rescue => e
|
41
|
+
return block.call(e)
|
42
|
+
end
|
43
|
+
doc.version = response['_version']
|
29
44
|
doc.persisted!
|
45
|
+
block.call
|
30
46
|
end
|
31
47
|
|
32
|
-
def destroy(doc)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
48
|
+
def destroy(doc, &block)
|
49
|
+
block ||= DEFAULT_HANDLER
|
50
|
+
begin
|
51
|
+
response = Elastictastic.client.delete(
|
52
|
+
doc.index.name,
|
53
|
+
doc.class.type,
|
54
|
+
doc.id,
|
55
|
+
params_for(doc)
|
56
|
+
)
|
57
|
+
rescue => e
|
58
|
+
return block.call(e)
|
59
|
+
end
|
39
60
|
doc.transient!
|
61
|
+
block.call
|
40
62
|
response['found']
|
41
63
|
end
|
42
64
|
|
@@ -46,6 +68,9 @@ module Elastictastic
|
|
46
68
|
{}.tap do |params|
|
47
69
|
params[:refresh] = true if Elastictastic.config.auto_refresh
|
48
70
|
params[:parent] = doc._parent_id if doc._parent_id
|
71
|
+
params[:version] = doc.version if doc.version
|
72
|
+
routing = doc.class.route(doc)
|
73
|
+
params[:routing] = routing if routing
|
49
74
|
end
|
50
75
|
end
|
51
76
|
end
|
@@ -3,96 +3,12 @@ module Elastictastic
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
|
7
|
-
include Properties
|
8
|
-
include Persistence
|
9
|
-
include ParentChild
|
6
|
+
include BasicDocument
|
10
7
|
include Callbacks
|
11
8
|
include Observing
|
12
9
|
include Dirty
|
13
10
|
include MassAssignmentSecurity
|
14
11
|
include Validations
|
15
|
-
|
16
|
-
extend ActiveModel::Naming
|
17
|
-
include ActiveModel::Conversion
|
18
|
-
end
|
19
|
-
|
20
|
-
module ClassMethods
|
21
|
-
delegate :find, :destroy_all, :sync_mapping, :inspect, :find_each,
|
22
|
-
:find_in_batches, :first, :count, :empty?, :any?, :all,
|
23
|
-
:query, :filter, :from, :size, :sort, :highlight, :fields,
|
24
|
-
:script_fields, :preference, :facets, :to => :current_scope
|
25
|
-
|
26
|
-
def mapping
|
27
|
-
{ type => { 'properties' => properties }}
|
28
|
-
end
|
29
|
-
|
30
|
-
def type
|
31
|
-
name.underscore
|
32
|
-
end
|
33
|
-
|
34
|
-
def in_index(name_or_index)
|
35
|
-
Scope.new(Elastictastic::Index(name_or_index), self)
|
36
|
-
end
|
37
|
-
|
38
|
-
def scoped(params)
|
39
|
-
current_scope.scoped(params)
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def default_scope
|
45
|
-
in_index(Index.default)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
module InstanceMethods
|
50
|
-
attr_reader :id
|
51
|
-
|
52
|
-
def initialize(attributes = {})
|
53
|
-
self.class.current_scope.initialize_instance(self)
|
54
|
-
end
|
55
|
-
|
56
|
-
def elasticsearch_hit=(hit) #:nodoc:
|
57
|
-
@id = hit['_id']
|
58
|
-
@index = Index.new(hit['_index'])
|
59
|
-
persisted!
|
60
|
-
|
61
|
-
doc = {}
|
62
|
-
doc.merge!(hit['_source']) if hit['_source']
|
63
|
-
fields = hit['fields']
|
64
|
-
if fields
|
65
|
-
unflattened_fields =
|
66
|
-
Util.unflatten_hash(fields.reject { |k, v| v.nil? })
|
67
|
-
if unflattened_fields.has_key?('_source')
|
68
|
-
doc.merge!(unflattened_fields.delete('_source'))
|
69
|
-
end
|
70
|
-
doc.merge!(unflattened_fields)
|
71
|
-
end
|
72
|
-
self.elasticsearch_doc=(doc)
|
73
|
-
end
|
74
|
-
|
75
|
-
def id=(id)
|
76
|
-
assert_transient!
|
77
|
-
@id = id
|
78
|
-
end
|
79
|
-
|
80
|
-
def index
|
81
|
-
return @index if defined? @index
|
82
|
-
@index = Index.default
|
83
|
-
end
|
84
|
-
|
85
|
-
def ==(other)
|
86
|
-
index == other.index && id == other.id
|
87
|
-
end
|
88
|
-
|
89
|
-
def inspect
|
90
|
-
inspected = "#<#{self.class.name} id: #{id}, index: #{index.name}"
|
91
|
-
attributes.each_pair do |attr, value|
|
92
|
-
inspected << ", #{attr}: #{value.inspect}"
|
93
|
-
end
|
94
|
-
inspected << ">"
|
95
|
-
end
|
96
12
|
end
|
97
13
|
end
|
98
14
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Elastictastic
|
2
|
+
module EmbeddedDocument
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
include Properties
|
7
|
+
include Dirty
|
8
|
+
include Dirty::EmbeddedDocumentMethods
|
9
|
+
include MassAssignmentSecurity
|
10
|
+
include Validations
|
11
|
+
|
12
|
+
include ActiveModel::Serializers::JSON
|
13
|
+
include ActiveModel::Serializers::Xml
|
14
|
+
|
15
|
+
self.include_root_in_json = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize_copy(original)
|
19
|
+
self.write_attributes(original.read_attributes.dup)
|
20
|
+
end
|
21
|
+
|
22
|
+
def attributes
|
23
|
+
{}
|
24
|
+
end
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
other.nil? ? false : @_attributes == other.read_attributes && @_embeds == other.read_embeds
|
28
|
+
end
|
29
|
+
|
30
|
+
def eql?(other)
|
31
|
+
self.class == other.class && self == other
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/elastictastic/errors.rb
CHANGED
@@ -1,7 +1,19 @@
|
|
1
1
|
module Elastictastic
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
Error = Class.new(StandardError)
|
3
|
+
CancelSave = Class.new(Error)
|
4
|
+
IllegalModificationError = Class.new(Error)
|
5
|
+
OperationNotAllowed = Class.new(Error)
|
6
|
+
MissingParameter = Class.new(Error)
|
7
|
+
|
8
|
+
class ConnectionFailed < Error
|
9
|
+
attr_reader :source
|
10
|
+
|
11
|
+
def initialize(source)
|
12
|
+
super(source.message)
|
13
|
+
@source = source
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
NoServerAvailable = Class.new(ConnectionFailed)
|
18
|
+
RecordInvalid = Class.new(Error)
|
7
19
|
end
|
data/lib/elastictastic/field.rb
CHANGED
@@ -10,6 +10,9 @@ module Elastictastic
|
|
10
10
|
|
11
11
|
def self.with_defaults(options)
|
12
12
|
options = Util.deep_stringify(options)
|
13
|
+
if preset = options.delete('preset')
|
14
|
+
options = ::Elastictastic.config.presets[preset].merge(options)
|
15
|
+
end
|
13
16
|
{ 'type' => 'string' }.merge(options).tap do |field_properties|
|
14
17
|
if field_properties['type'].to_s == 'date'
|
15
18
|
field_properties['format'] = 'date_time_no_millis'
|
@@ -6,10 +6,8 @@ module Elastictastic
|
|
6
6
|
include ActiveModel::MassAssignmentSecurity
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
super(sanitize_for_mass_assignment(attributes))
|
12
|
-
end
|
9
|
+
def attributes=(attributes)
|
10
|
+
super(sanitize_for_mass_assignment(attributes))
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|