elasticsearch-persistence 5.1.0 → 6.0.0.pre
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 +4 -4
- data/.rspec +2 -0
- data/Gemfile +9 -0
- data/README.md +164 -323
- data/Rakefile +8 -8
- data/elasticsearch-persistence.gemspec +4 -5
- data/lib/elasticsearch/persistence.rb +2 -110
- data/lib/elasticsearch/persistence/repository.rb +212 -53
- data/lib/elasticsearch/persistence/repository/dsl.rb +94 -0
- data/lib/elasticsearch/persistence/repository/find.rb +27 -10
- data/lib/elasticsearch/persistence/repository/response/results.rb +17 -5
- data/lib/elasticsearch/persistence/repository/search.rb +15 -4
- data/lib/elasticsearch/persistence/repository/serialize.rb +65 -7
- data/lib/elasticsearch/persistence/repository/store.rb +38 -44
- data/lib/elasticsearch/persistence/version.rb +1 -1
- data/spec/repository/find_spec.rb +179 -0
- data/spec/repository/response/results_spec.rb +105 -0
- data/spec/repository/search_spec.rb +181 -0
- data/spec/repository/serialize_spec.rb +53 -0
- data/spec/repository/store_spec.rb +327 -0
- data/spec/repository_spec.rb +716 -0
- data/spec/spec_helper.rb +28 -0
- metadata +25 -80
- data/lib/elasticsearch/persistence/client.rb +0 -51
- data/lib/elasticsearch/persistence/model.rb +0 -153
- data/lib/elasticsearch/persistence/model/base.rb +0 -87
- data/lib/elasticsearch/persistence/model/errors.rb +0 -8
- data/lib/elasticsearch/persistence/model/find.rb +0 -180
- data/lib/elasticsearch/persistence/model/rails.rb +0 -47
- data/lib/elasticsearch/persistence/model/store.rb +0 -254
- data/lib/elasticsearch/persistence/model/utils.rb +0 -0
- data/lib/elasticsearch/persistence/repository/class.rb +0 -71
- data/lib/elasticsearch/persistence/repository/naming.rb +0 -115
- data/lib/rails/generators/elasticsearch/model/model_generator.rb +0 -21
- data/lib/rails/generators/elasticsearch/model/templates/model.rb.tt +0 -9
- data/lib/rails/generators/elasticsearch_generator.rb +0 -2
- data/test/integration/model/model_basic_test.rb +0 -238
- data/test/integration/repository/custom_class_test.rb +0 -85
- data/test/integration/repository/customized_class_test.rb +0 -82
- data/test/integration/repository/default_class_test.rb +0 -116
- data/test/integration/repository/virtus_model_test.rb +0 -118
- data/test/test_helper.rb +0 -55
- data/test/unit/model_base_test.rb +0 -72
- data/test/unit/model_find_test.rb +0 -153
- data/test/unit/model_gateway_test.rb +0 -101
- data/test/unit/model_rails_test.rb +0 -112
- data/test/unit/model_store_test.rb +0 -576
- data/test/unit/persistence_test.rb +0 -32
- data/test/unit/repository_class_test.rb +0 -51
- data/test/unit/repository_client_test.rb +0 -32
- data/test/unit/repository_find_test.rb +0 -388
- data/test/unit/repository_indexing_test.rb +0 -37
- data/test/unit/repository_module_test.rb +0 -146
- data/test/unit/repository_naming_test.rb +0 -146
- data/test/unit/repository_response_results_test.rb +0 -98
- data/test/unit/repository_search_test.rb +0 -117
- data/test/unit/repository_serialize_test.rb +0 -57
- data/test/unit/repository_store_test.rb +0 -303
File without changes
|
@@ -1,71 +0,0 @@
|
|
1
|
-
module Elasticsearch
|
2
|
-
module Persistence
|
3
|
-
module Repository
|
4
|
-
|
5
|
-
# The default repository class, to be used either directly, or as a gateway in a custom repository class
|
6
|
-
#
|
7
|
-
# @example Standalone use
|
8
|
-
#
|
9
|
-
# repository = Elasticsearch::Persistence::Repository::Class.new
|
10
|
-
# # => #<Elasticsearch::Persistence::Repository::Class ...>
|
11
|
-
# repository.save(my_object)
|
12
|
-
# # => {"_index"=> ... }
|
13
|
-
#
|
14
|
-
# @example Shortcut use
|
15
|
-
#
|
16
|
-
# repository = Elasticsearch::Persistence::Repository.new
|
17
|
-
# # => #<Elasticsearch::Persistence::Repository::Class ...>
|
18
|
-
#
|
19
|
-
# @example Configuration via a block
|
20
|
-
#
|
21
|
-
# repository = Elasticsearch::Persistence::Repository.new do
|
22
|
-
# index 'my_notes'
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# # => #<Elasticsearch::Persistence::Repository::Class ...>
|
26
|
-
# # > repository.save(my_object)
|
27
|
-
# # => {"_index"=> ... }
|
28
|
-
#
|
29
|
-
# @example Accessing the gateway in a custom class
|
30
|
-
#
|
31
|
-
# class MyRepository
|
32
|
-
# include Elasticsearch::Persistence::Repository
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
# repository = MyRepository.new
|
36
|
-
#
|
37
|
-
# repository.gateway.client.info
|
38
|
-
# # => {"status"=>200, "name"=>"Venom", ... }
|
39
|
-
#
|
40
|
-
class Class
|
41
|
-
include Elasticsearch::Persistence::Repository::Client
|
42
|
-
include Elasticsearch::Persistence::Repository::Naming
|
43
|
-
include Elasticsearch::Persistence::Repository::Serialize
|
44
|
-
include Elasticsearch::Persistence::Repository::Store
|
45
|
-
include Elasticsearch::Persistence::Repository::Find
|
46
|
-
include Elasticsearch::Persistence::Repository::Search
|
47
|
-
|
48
|
-
include Elasticsearch::Model::Indexing::ClassMethods
|
49
|
-
|
50
|
-
attr_reader :options
|
51
|
-
|
52
|
-
def initialize(options={}, &block)
|
53
|
-
@options = options
|
54
|
-
index_name options.delete(:index)
|
55
|
-
block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
|
56
|
-
end
|
57
|
-
|
58
|
-
# Return the "host" class, if this repository is a gateway hosted in another class
|
59
|
-
#
|
60
|
-
# @return [nil, Class]
|
61
|
-
#
|
62
|
-
# @api private
|
63
|
-
#
|
64
|
-
def host
|
65
|
-
options[:host]
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
module Elasticsearch
|
2
|
-
module Persistence
|
3
|
-
module Repository
|
4
|
-
|
5
|
-
# Wraps all naming-related features of the repository (index name, the domain object class, etc)
|
6
|
-
#
|
7
|
-
module Naming
|
8
|
-
|
9
|
-
# Get or set the class used to initialize domain objects when deserializing them
|
10
|
-
#
|
11
|
-
def klass name=nil
|
12
|
-
@klass = name || @klass
|
13
|
-
end
|
14
|
-
|
15
|
-
# Set the class used to initialize domain objects when deserializing them
|
16
|
-
#
|
17
|
-
def klass=klass
|
18
|
-
@klass = klass
|
19
|
-
end
|
20
|
-
|
21
|
-
# Get or set the index name used when storing and retrieving documents
|
22
|
-
#
|
23
|
-
def index_name name=nil
|
24
|
-
@index_name = name || @index_name || begin
|
25
|
-
if respond_to?(:host) && host && host.is_a?(Module)
|
26
|
-
self.host.to_s.underscore.gsub(/\//, '-')
|
27
|
-
else
|
28
|
-
self.class.to_s.underscore.gsub(/\//, '-')
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end; alias :index :index_name
|
32
|
-
|
33
|
-
# Set the index name used when storing and retrieving documents
|
34
|
-
#
|
35
|
-
def index_name=(name)
|
36
|
-
@index_name = name
|
37
|
-
end; alias :index= :index_name=
|
38
|
-
|
39
|
-
# Get or set the document type used when storing and retrieving documents
|
40
|
-
#
|
41
|
-
def document_type name=nil
|
42
|
-
@document_type = name || @document_type || (klass ? klass.to_s.underscore : nil)
|
43
|
-
end; alias :type :document_type
|
44
|
-
|
45
|
-
# Set the document type used when storing and retrieving documents
|
46
|
-
#
|
47
|
-
def document_type=(name)
|
48
|
-
@document_type = name
|
49
|
-
end; alias :type= :document_type=
|
50
|
-
|
51
|
-
# Get the Ruby class from the Elasticsearch `_type`
|
52
|
-
#
|
53
|
-
# @example
|
54
|
-
# repository.__get_klass_from_type 'note'
|
55
|
-
# => Note
|
56
|
-
#
|
57
|
-
# @return [Class] The class corresponding to the passed type
|
58
|
-
# @raise [NameError] if the class cannot be found
|
59
|
-
#
|
60
|
-
# @api private
|
61
|
-
#
|
62
|
-
def __get_klass_from_type(type)
|
63
|
-
klass = type.classify
|
64
|
-
klass.constantize
|
65
|
-
rescue NameError => e
|
66
|
-
raise NameError, "Attempted to get class '#{klass}' from the '#{type}' type, but no such class can be found."
|
67
|
-
end
|
68
|
-
|
69
|
-
# Get the Elasticsearch `_type` from the Ruby class
|
70
|
-
#
|
71
|
-
# @example
|
72
|
-
# repository.__get_type_from_class Note
|
73
|
-
# => "note"
|
74
|
-
#
|
75
|
-
# @return [String] The type corresponding to the passed class
|
76
|
-
#
|
77
|
-
# @api private
|
78
|
-
#
|
79
|
-
def __get_type_from_class(klass)
|
80
|
-
klass.to_s.underscore
|
81
|
-
end
|
82
|
-
|
83
|
-
# Get a document ID from the document (assuming Hash or Hash-like object)
|
84
|
-
#
|
85
|
-
# @example
|
86
|
-
# repository.__get_id_from_document title: 'Test', id: 'abc123'
|
87
|
-
# => "abc123"
|
88
|
-
#
|
89
|
-
# @api private
|
90
|
-
#
|
91
|
-
def __get_id_from_document(document)
|
92
|
-
document[:id] || document['id'] || document[:_id] || document['_id']
|
93
|
-
end
|
94
|
-
|
95
|
-
# Extract a document ID from the document (assuming Hash or Hash-like object)
|
96
|
-
#
|
97
|
-
# @note Calling this method will *remove* the `id` or `_id` key from the passed object.
|
98
|
-
#
|
99
|
-
# @example
|
100
|
-
# options = { title: 'Test', id: 'abc123' }
|
101
|
-
# repository.__extract_id_from_document options
|
102
|
-
# # => "abc123"
|
103
|
-
# options
|
104
|
-
# # => { title: 'Test' }
|
105
|
-
#
|
106
|
-
# @api private
|
107
|
-
#
|
108
|
-
def __extract_id_from_document(document)
|
109
|
-
document.delete(:id) || document.delete('id') || document.delete(:_id) || document.delete('_id')
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require "rails/generators/elasticsearch_generator"
|
2
|
-
|
3
|
-
module Elasticsearch
|
4
|
-
module Generators
|
5
|
-
class ModelGenerator < ::Rails::Generators::NamedBase
|
6
|
-
source_root File.expand_path('../templates', __FILE__)
|
7
|
-
|
8
|
-
desc "Creates an Elasticsearch::Persistence model"
|
9
|
-
argument :attributes, type: :array, default: [], banner: "attribute:type attribute:type"
|
10
|
-
|
11
|
-
check_class_collision
|
12
|
-
|
13
|
-
def create_model_file
|
14
|
-
@padding = attributes.map { |a| a.name.size }.max
|
15
|
-
template "model.rb.tt", File.join("app/models", class_path, "#{file_name}.rb")
|
16
|
-
end
|
17
|
-
|
18
|
-
hook_for :test_framework
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,238 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
require 'elasticsearch/persistence/model'
|
4
|
-
require 'elasticsearch/persistence/model/rails'
|
5
|
-
|
6
|
-
module Elasticsearch
|
7
|
-
module Persistence
|
8
|
-
class PersistenceModelBasicIntegrationTest < Elasticsearch::Test::IntegrationTestCase
|
9
|
-
|
10
|
-
class ::Person
|
11
|
-
include Elasticsearch::Persistence::Model
|
12
|
-
include Elasticsearch::Persistence::Model::Rails
|
13
|
-
|
14
|
-
settings index: { number_of_shards: 1 }
|
15
|
-
document_type 'human_being'
|
16
|
-
|
17
|
-
attribute :name, String,
|
18
|
-
mapping: { fields: {
|
19
|
-
name: { type: 'text', analyzer: 'snowball' },
|
20
|
-
raw: { type: 'keyword' }
|
21
|
-
} }
|
22
|
-
|
23
|
-
attribute :birthday, Date
|
24
|
-
attribute :department, String
|
25
|
-
attribute :salary, Integer
|
26
|
-
attribute :admin, Boolean, default: false
|
27
|
-
|
28
|
-
validates :name, presence: true
|
29
|
-
end
|
30
|
-
|
31
|
-
context "A basic persistence model" do
|
32
|
-
setup do
|
33
|
-
Person.create_index! force: true
|
34
|
-
end
|
35
|
-
|
36
|
-
should "warn that the ActiveRecord persistence pattern is deprecated" do
|
37
|
-
Kernel.expects(:warn).at_least_once
|
38
|
-
class ShouldWarn; include Elasticsearch::Persistence::Model; end
|
39
|
-
end
|
40
|
-
|
41
|
-
should "save the object with custom ID" do
|
42
|
-
person = Person.new id: 1, name: 'Number One'
|
43
|
-
person.save
|
44
|
-
|
45
|
-
document = Person.find(1)
|
46
|
-
assert_not_nil document
|
47
|
-
assert_equal 'Number One', document.name
|
48
|
-
end
|
49
|
-
|
50
|
-
should "create the object with custom ID" do
|
51
|
-
person = Person.create id: 1, name: 'Number One'
|
52
|
-
|
53
|
-
document = Person.find(1)
|
54
|
-
assert_not_nil document
|
55
|
-
assert_equal 'Number One', document.name
|
56
|
-
end
|
57
|
-
|
58
|
-
should "save and find the object" do
|
59
|
-
person = Person.new name: 'John Smith', birthday: Date.parse('1970-01-01')
|
60
|
-
assert person.save
|
61
|
-
|
62
|
-
assert_not_nil person.id
|
63
|
-
document = Person.find(person.id)
|
64
|
-
|
65
|
-
assert_instance_of Person, document
|
66
|
-
assert_equal 'John Smith', document.name
|
67
|
-
assert_equal 'John Smith', Person.find(person.id).name
|
68
|
-
|
69
|
-
assert_not_nil Elasticsearch::Persistence.client.get index: 'people', type: 'human_being', id: person.id
|
70
|
-
end
|
71
|
-
|
72
|
-
should "not save an invalid object" do
|
73
|
-
person = Person.new name: nil
|
74
|
-
assert ! person.save
|
75
|
-
end
|
76
|
-
|
77
|
-
should "save an invalid object with the :validate option" do
|
78
|
-
person = Person.new name: nil, salary: 100
|
79
|
-
assert person.save validate: false
|
80
|
-
|
81
|
-
assert_not_nil person.id
|
82
|
-
document = Person.find(person.id)
|
83
|
-
assert_equal 100, document.salary
|
84
|
-
end
|
85
|
-
|
86
|
-
should "delete the object" do
|
87
|
-
person = Person.create name: 'John Smith', birthday: Date.parse('1970-01-01')
|
88
|
-
|
89
|
-
person.destroy
|
90
|
-
assert person.frozen?
|
91
|
-
|
92
|
-
assert_raise Elasticsearch::Transport::Transport::Errors::NotFound do
|
93
|
-
Elasticsearch::Persistence.client.get index: 'people', type: 'person', id: person.id
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
should "update an object attribute" do
|
98
|
-
person = Person.create name: 'John Smith'
|
99
|
-
|
100
|
-
person.update name: 'UPDATED'
|
101
|
-
|
102
|
-
assert_equal 'UPDATED', person.name
|
103
|
-
assert_equal 'UPDATED', Person.find(person.id).name
|
104
|
-
end
|
105
|
-
|
106
|
-
should "create the model with correct Date form Rails' form attributes" do
|
107
|
-
params = { "birthday(1i)"=>"2014",
|
108
|
-
"birthday(2i)"=>"1",
|
109
|
-
"birthday(3i)"=>"1"
|
110
|
-
}
|
111
|
-
person = Person.create params.merge(name: 'TEST')
|
112
|
-
|
113
|
-
assert_equal Date.parse('2014-01-01'), person.birthday
|
114
|
-
assert_equal Date.parse('2014-01-01'), Person.find(person.id).birthday
|
115
|
-
end
|
116
|
-
|
117
|
-
should_eventually "update the model with correct Date form Rails' form attributes" do
|
118
|
-
params = { "birthday(1i)"=>"2014",
|
119
|
-
"birthday(2i)"=>"1",
|
120
|
-
"birthday(3i)"=>"1"
|
121
|
-
}
|
122
|
-
person = Person.create params.merge(name: 'TEST')
|
123
|
-
|
124
|
-
person.update params.merge('birthday(1i)' => '2015')
|
125
|
-
|
126
|
-
assert_equal Date.parse('2015-01-01'), person.birthday
|
127
|
-
assert_equal Date.parse('2015-01-01'), Person.find(person.id).birthday
|
128
|
-
end
|
129
|
-
|
130
|
-
should "increment an object attribute" do
|
131
|
-
person = Person.create name: 'John Smith', salary: 1_000
|
132
|
-
|
133
|
-
person.increment :salary
|
134
|
-
|
135
|
-
assert_equal 1_001, person.salary
|
136
|
-
assert_equal 1_001, Person.find(person.id).salary
|
137
|
-
end
|
138
|
-
|
139
|
-
should "update the object timestamp" do
|
140
|
-
person = Person.create name: 'John Smith'
|
141
|
-
updated_at = person.updated_at
|
142
|
-
|
143
|
-
sleep 1
|
144
|
-
person.touch
|
145
|
-
|
146
|
-
assert person.updated_at > updated_at, [person.updated_at, updated_at].inspect
|
147
|
-
|
148
|
-
found = Person.find(person.id)
|
149
|
-
assert found.updated_at > updated_at, [found.updated_at, updated_at].inspect
|
150
|
-
end
|
151
|
-
|
152
|
-
should 'update the object timestamp on save' do
|
153
|
-
person = Person.create name: 'John Smith'
|
154
|
-
person.admin = true
|
155
|
-
sleep 1
|
156
|
-
person.save
|
157
|
-
|
158
|
-
Person.gateway.refresh_index!
|
159
|
-
|
160
|
-
found = Person.find(person.id)
|
161
|
-
|
162
|
-
# Compare without milliseconds
|
163
|
-
assert_equal person.updated_at.to_i, found.updated_at.to_i
|
164
|
-
end
|
165
|
-
|
166
|
-
should "respect the version" do
|
167
|
-
person = Person.create name: 'John Smith'
|
168
|
-
|
169
|
-
person.update( { name: 'UPDATE 1' })
|
170
|
-
|
171
|
-
assert_raise Elasticsearch::Transport::Transport::Errors::Conflict do
|
172
|
-
person.update( { name: 'UPDATE 2' }, { version: 1 } )
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
should "find all instances" do
|
177
|
-
Person.create name: 'John Smith'
|
178
|
-
Person.create name: 'Mary Smith'
|
179
|
-
Person.gateway.refresh_index!
|
180
|
-
|
181
|
-
people = Person.all
|
182
|
-
|
183
|
-
assert_equal 2, people.total
|
184
|
-
assert_equal 2, people.size
|
185
|
-
end
|
186
|
-
|
187
|
-
should "find instances by search" do
|
188
|
-
Person.create name: 'John Smith'
|
189
|
-
Person.create name: 'Mary Smith'
|
190
|
-
Person.gateway.refresh_index!
|
191
|
-
|
192
|
-
people = Person.search query: { match: { name: 'smith' } },
|
193
|
-
highlight: { fields: { name: {} } }
|
194
|
-
|
195
|
-
assert_equal 2, people.total
|
196
|
-
assert_equal 2, people.size
|
197
|
-
|
198
|
-
assert people.map_with_hit { |o,h| h._score }.all? { |s| s > 0 }
|
199
|
-
|
200
|
-
assert_not_nil people.first.hit
|
201
|
-
assert_match /smith/i, people.first.hit.highlight['name'].first
|
202
|
-
end
|
203
|
-
|
204
|
-
should "find instances in batches" do
|
205
|
-
50.times { |i| Person.create name: "John #{i+1}" }
|
206
|
-
Person.gateway.refresh_index!
|
207
|
-
|
208
|
-
@batches = 0
|
209
|
-
@results = []
|
210
|
-
|
211
|
-
Person.find_in_batches(_source_include: 'name') do |batch|
|
212
|
-
@batches += 1
|
213
|
-
@results += batch.map(&:name)
|
214
|
-
end
|
215
|
-
|
216
|
-
assert_equal 3, @batches
|
217
|
-
assert_equal 50, @results.size
|
218
|
-
assert_contains @results, 'John 1'
|
219
|
-
end
|
220
|
-
|
221
|
-
should "find each instance" do
|
222
|
-
50.times { |i| Person.create name: "John #{i+1}" }
|
223
|
-
Person.gateway.refresh_index!
|
224
|
-
|
225
|
-
@results = []
|
226
|
-
|
227
|
-
Person.find_each(_source_include: 'name') do |person|
|
228
|
-
@results << person.name
|
229
|
-
end
|
230
|
-
|
231
|
-
assert_equal 50, @results.size
|
232
|
-
assert_contains @results, 'John 1'
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|