elasticsearch-persistence 5.0.2 → 6.1.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.
Files changed (81) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +2 -0
  3. data/Gemfile +9 -0
  4. data/README.md +206 -338
  5. data/Rakefile +15 -12
  6. data/elasticsearch-persistence.gemspec +6 -7
  7. data/examples/notes/application.rb +3 -4
  8. data/lib/elasticsearch/persistence.rb +2 -110
  9. data/lib/elasticsearch/persistence/repository.rb +212 -53
  10. data/lib/elasticsearch/persistence/repository/dsl.rb +94 -0
  11. data/lib/elasticsearch/persistence/repository/find.rb +27 -10
  12. data/lib/elasticsearch/persistence/repository/response/results.rb +21 -8
  13. data/lib/elasticsearch/persistence/repository/search.rb +30 -18
  14. data/lib/elasticsearch/persistence/repository/serialize.rb +65 -7
  15. data/lib/elasticsearch/persistence/repository/store.rb +38 -44
  16. data/lib/elasticsearch/persistence/version.rb +1 -1
  17. data/spec/repository/find_spec.rb +179 -0
  18. data/spec/repository/response/results_spec.rb +128 -0
  19. data/spec/repository/search_spec.rb +181 -0
  20. data/spec/repository/serialize_spec.rb +53 -0
  21. data/spec/repository/store_spec.rb +327 -0
  22. data/spec/repository_spec.rb +723 -0
  23. data/spec/spec_helper.rb +32 -0
  24. metadata +26 -104
  25. data/examples/music/album.rb +0 -54
  26. data/examples/music/artist.rb +0 -70
  27. data/examples/music/artists/_form.html.erb +0 -8
  28. data/examples/music/artists/artists_controller.rb +0 -67
  29. data/examples/music/artists/artists_controller_test.rb +0 -53
  30. data/examples/music/artists/index.html.erb +0 -60
  31. data/examples/music/artists/show.html.erb +0 -54
  32. data/examples/music/assets/application.css +0 -257
  33. data/examples/music/assets/autocomplete.css +0 -48
  34. data/examples/music/assets/blank_artist.png +0 -0
  35. data/examples/music/assets/blank_cover.png +0 -0
  36. data/examples/music/assets/form.css +0 -113
  37. data/examples/music/index_manager.rb +0 -73
  38. data/examples/music/search/index.html.erb +0 -95
  39. data/examples/music/search/search_controller.rb +0 -41
  40. data/examples/music/search/search_controller_test.rb +0 -12
  41. data/examples/music/search/search_helper.rb +0 -15
  42. data/examples/music/suggester.rb +0 -69
  43. data/examples/music/template.rb +0 -430
  44. data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.css +0 -7
  45. data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.js +0 -6
  46. data/examples/music/vendor/assets/stylesheets/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  47. data/lib/elasticsearch/persistence/client.rb +0 -51
  48. data/lib/elasticsearch/persistence/model.rb +0 -135
  49. data/lib/elasticsearch/persistence/model/base.rb +0 -87
  50. data/lib/elasticsearch/persistence/model/errors.rb +0 -8
  51. data/lib/elasticsearch/persistence/model/find.rb +0 -180
  52. data/lib/elasticsearch/persistence/model/rails.rb +0 -47
  53. data/lib/elasticsearch/persistence/model/store.rb +0 -254
  54. data/lib/elasticsearch/persistence/model/utils.rb +0 -0
  55. data/lib/elasticsearch/persistence/repository/class.rb +0 -71
  56. data/lib/elasticsearch/persistence/repository/naming.rb +0 -115
  57. data/lib/rails/generators/elasticsearch/model/model_generator.rb +0 -21
  58. data/lib/rails/generators/elasticsearch/model/templates/model.rb.tt +0 -9
  59. data/lib/rails/generators/elasticsearch_generator.rb +0 -2
  60. data/test/integration/model/model_basic_test.rb +0 -233
  61. data/test/integration/repository/custom_class_test.rb +0 -85
  62. data/test/integration/repository/customized_class_test.rb +0 -82
  63. data/test/integration/repository/default_class_test.rb +0 -116
  64. data/test/integration/repository/virtus_model_test.rb +0 -118
  65. data/test/test_helper.rb +0 -55
  66. data/test/unit/model_base_test.rb +0 -72
  67. data/test/unit/model_find_test.rb +0 -153
  68. data/test/unit/model_gateway_test.rb +0 -101
  69. data/test/unit/model_rails_test.rb +0 -112
  70. data/test/unit/model_store_test.rb +0 -576
  71. data/test/unit/persistence_test.rb +0 -32
  72. data/test/unit/repository_class_test.rb +0 -51
  73. data/test/unit/repository_client_test.rb +0 -32
  74. data/test/unit/repository_find_test.rb +0 -388
  75. data/test/unit/repository_indexing_test.rb +0 -37
  76. data/test/unit/repository_module_test.rb +0 -146
  77. data/test/unit/repository_naming_test.rb +0 -146
  78. data/test/unit/repository_response_results_test.rb +0 -98
  79. data/test/unit/repository_search_test.rb +0 -117
  80. data/test/unit/repository_serialize_test.rb +0 -57
  81. data/test/unit/repository_store_test.rb +0 -303
@@ -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,9 +0,0 @@
1
- <% module_namespacing do -%>
2
- class <%= class_name %>
3
- include Elasticsearch::Persistence::Model
4
-
5
- <% attributes.each do |attribute| -%>
6
- <%= "attribute :#{attribute.name},".ljust(@padding+12) %> <%= attribute.type %>
7
- <% end -%>
8
- end
9
- <% end -%>
@@ -1,2 +0,0 @@
1
- require "rails/generators/named_base"
2
- require "rails/generators/active_model"
@@ -1,233 +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 "save the object with custom ID" do
37
- person = Person.new id: 1, name: 'Number One'
38
- person.save
39
-
40
- document = Person.find(1)
41
- assert_not_nil document
42
- assert_equal 'Number One', document.name
43
- end
44
-
45
- should "create the object with custom ID" do
46
- person = Person.create id: 1, name: 'Number One'
47
-
48
- document = Person.find(1)
49
- assert_not_nil document
50
- assert_equal 'Number One', document.name
51
- end
52
-
53
- should "save and find the object" do
54
- person = Person.new name: 'John Smith', birthday: Date.parse('1970-01-01')
55
- assert person.save
56
-
57
- assert_not_nil person.id
58
- document = Person.find(person.id)
59
-
60
- assert_instance_of Person, document
61
- assert_equal 'John Smith', document.name
62
- assert_equal 'John Smith', Person.find(person.id).name
63
-
64
- assert_not_nil Elasticsearch::Persistence.client.get index: 'people', type: 'human_being', id: person.id
65
- end
66
-
67
- should "not save an invalid object" do
68
- person = Person.new name: nil
69
- assert ! person.save
70
- end
71
-
72
- should "save an invalid object with the :validate option" do
73
- person = Person.new name: nil, salary: 100
74
- assert person.save validate: false
75
-
76
- assert_not_nil person.id
77
- document = Person.find(person.id)
78
- assert_equal 100, document.salary
79
- end
80
-
81
- should "delete the object" do
82
- person = Person.create name: 'John Smith', birthday: Date.parse('1970-01-01')
83
-
84
- person.destroy
85
- assert person.frozen?
86
-
87
- assert_raise Elasticsearch::Transport::Transport::Errors::NotFound do
88
- Elasticsearch::Persistence.client.get index: 'people', type: 'person', id: person.id
89
- end
90
- end
91
-
92
- should "update an object attribute" do
93
- person = Person.create name: 'John Smith'
94
-
95
- person.update name: 'UPDATED'
96
-
97
- assert_equal 'UPDATED', person.name
98
- assert_equal 'UPDATED', Person.find(person.id).name
99
- end
100
-
101
- should "create the model with correct Date form Rails' form attributes" do
102
- params = { "birthday(1i)"=>"2014",
103
- "birthday(2i)"=>"1",
104
- "birthday(3i)"=>"1"
105
- }
106
- person = Person.create params.merge(name: 'TEST')
107
-
108
- assert_equal Date.parse('2014-01-01'), person.birthday
109
- assert_equal Date.parse('2014-01-01'), Person.find(person.id).birthday
110
- end
111
-
112
- should_eventually "update the model with correct Date form Rails' form attributes" do
113
- params = { "birthday(1i)"=>"2014",
114
- "birthday(2i)"=>"1",
115
- "birthday(3i)"=>"1"
116
- }
117
- person = Person.create params.merge(name: 'TEST')
118
-
119
- person.update params.merge('birthday(1i)' => '2015')
120
-
121
- assert_equal Date.parse('2015-01-01'), person.birthday
122
- assert_equal Date.parse('2015-01-01'), Person.find(person.id).birthday
123
- end
124
-
125
- should "increment an object attribute" do
126
- person = Person.create name: 'John Smith', salary: 1_000
127
-
128
- person.increment :salary
129
-
130
- assert_equal 1_001, person.salary
131
- assert_equal 1_001, Person.find(person.id).salary
132
- end
133
-
134
- should "update the object timestamp" do
135
- person = Person.create name: 'John Smith'
136
- updated_at = person.updated_at
137
-
138
- sleep 1
139
- person.touch
140
-
141
- assert person.updated_at > updated_at, [person.updated_at, updated_at].inspect
142
-
143
- found = Person.find(person.id)
144
- assert found.updated_at > updated_at, [found.updated_at, updated_at].inspect
145
- end
146
-
147
- should 'update the object timestamp on save' do
148
- person = Person.create name: 'John Smith'
149
- person.admin = true
150
- sleep 1
151
- person.save
152
-
153
- Person.gateway.refresh_index!
154
-
155
- found = Person.find(person.id)
156
-
157
- # Compare without milliseconds
158
- assert_equal person.updated_at.to_i, found.updated_at.to_i
159
- end
160
-
161
- should "respect the version" do
162
- person = Person.create name: 'John Smith'
163
-
164
- person.update( { name: 'UPDATE 1' })
165
-
166
- assert_raise Elasticsearch::Transport::Transport::Errors::Conflict do
167
- person.update( { name: 'UPDATE 2' }, { version: 1 } )
168
- end
169
- end
170
-
171
- should "find all instances" do
172
- Person.create name: 'John Smith'
173
- Person.create name: 'Mary Smith'
174
- Person.gateway.refresh_index!
175
-
176
- people = Person.all
177
-
178
- assert_equal 2, people.total
179
- assert_equal 2, people.size
180
- end
181
-
182
- should "find instances by search" do
183
- Person.create name: 'John Smith'
184
- Person.create name: 'Mary Smith'
185
- Person.gateway.refresh_index!
186
-
187
- people = Person.search query: { match: { name: 'smith' } },
188
- highlight: { fields: { name: {} } }
189
-
190
- assert_equal 2, people.total
191
- assert_equal 2, people.size
192
-
193
- assert people.map_with_hit { |o,h| h._score }.all? { |s| s > 0 }
194
-
195
- assert_not_nil people.first.hit
196
- assert_match /smith/i, people.first.hit.highlight['name'].first
197
- end
198
-
199
- should "find instances in batches" do
200
- 50.times { |i| Person.create name: "John #{i+1}" }
201
- Person.gateway.refresh_index!
202
-
203
- @batches = 0
204
- @results = []
205
-
206
- Person.find_in_batches(_source_include: 'name') do |batch|
207
- @batches += 1
208
- @results += batch.map(&:name)
209
- end
210
-
211
- assert_equal 3, @batches
212
- assert_equal 50, @results.size
213
- assert_contains @results, 'John 1'
214
- end
215
-
216
- should "find each instance" do
217
- 50.times { |i| Person.create name: "John #{i+1}" }
218
- Person.gateway.refresh_index!
219
-
220
- @results = []
221
-
222
- Person.find_each(_source_include: 'name') do |person|
223
- @results << person.name
224
- end
225
-
226
- assert_equal 50, @results.size
227
- assert_contains @results, 'John 1'
228
- end
229
- end
230
-
231
- end
232
- end
233
- end
@@ -1,85 +0,0 @@
1
- require 'test_helper'
2
-
3
- module Elasticsearch
4
- module Persistence
5
- class RepositoryCustomClassIntegrationTest < Elasticsearch::Test::IntegrationTestCase
6
-
7
- class ::MyNote
8
- attr_reader :attributes
9
-
10
- def initialize(attributes={})
11
- @attributes = Hashie::Mash.new(attributes)
12
- end
13
-
14
- def method_missing(method_name, *arguments, &block)
15
- attributes.respond_to?(method_name) ? attributes.__send__(method_name, *arguments, &block) : super
16
- end
17
-
18
- def respond_to?(method_name, include_private=false)
19
- attributes.respond_to?(method_name) || super
20
- end
21
-
22
- def to_hash
23
- @attributes
24
- end
25
- end
26
-
27
- context "A custom repository class" do
28
- setup do
29
- class ::MyNotesRepository
30
- include Elasticsearch::Persistence::Repository
31
-
32
- klass MyNote
33
-
34
- settings number_of_shards: 1 do
35
- mapping do
36
- indexes :title, analyzer: 'snowball'
37
- end
38
- end
39
-
40
- create_index!
41
-
42
- def deserialize(document)
43
- klass.new document.merge(document['_source'])
44
- end
45
- end
46
-
47
- @repository = MyNotesRepository.new
48
-
49
- @repository.client.cluster.health wait_for_status: 'yellow'
50
- end
51
-
52
- should "save the object under a correct index and type" do
53
- @repository.save MyNote.new(id: '1', title: 'Test')
54
- result = @repository.find(1)
55
-
56
- assert_instance_of MyNote, result
57
- assert_equal 'Test', result.title
58
-
59
- assert_not_nil Elasticsearch::Persistence.client.get index: 'my_notes_repository',
60
- type: 'my_note',
61
- id: '1'
62
- end
63
-
64
- should "delete the object" do
65
- note = MyNote.new id: 1, title: 'Test'
66
- @repository.save note
67
-
68
- assert_not_nil @repository.find(1)
69
-
70
- @repository.delete(note)
71
- assert_raise(Elasticsearch::Persistence::Repository::DocumentNotFound) { @repository.find(1) }
72
- end
73
-
74
- should "retrieve the object via a search query" do
75
- note = MyNote.new title: 'Testing'
76
- @repository.save note, refresh: true
77
-
78
- results = @repository.search query: { match: { title: 'Test' } }
79
- assert_equal 'Testing', results.first.title
80
- end
81
- end
82
-
83
- end
84
- end
85
- end
@@ -1,82 +0,0 @@
1
- require 'test_helper'
2
-
3
- module Elasticsearch
4
- module Persistence
5
- class RepositoryCustomizedClassIntegrationTest < Elasticsearch::Test::IntegrationTestCase
6
-
7
- module ::My
8
- class Note
9
- attr_reader :attributes
10
-
11
- def initialize(attributes={})
12
- @attributes = attributes
13
- end
14
-
15
- def to_hash
16
- @attributes
17
- end
18
- end
19
- end
20
-
21
- context "A custom repository class" do
22
- setup do
23
- @repository = Elasticsearch::Persistence::Repository.new do
24
- index 'my_notes'
25
- type 'my_note'
26
- klass My::Note
27
-
28
- settings number_of_shards: 1 do
29
- mapping do
30
- indexes :title, analyzer: 'snowball'
31
- end
32
- end
33
-
34
- create_index!
35
- end
36
-
37
- @repository.client.cluster.health wait_for_status: 'yellow'
38
- end
39
-
40
- should "save the object under a correct index and type" do
41
- @repository.save My::Note.new(id: '1', title: 'Test')
42
-
43
- assert_instance_of My::Note, @repository.find(1)
44
- assert_not_nil Elasticsearch::Persistence.client.get index: 'my_notes', type: 'my_note', id: '1'
45
- end
46
-
47
- should "update the document" do
48
- @repository.save Note.new(id: 1, title: 'Test')
49
-
50
- @repository.update 1, doc: { title: 'UPDATED' }
51
- assert_equal 'UPDATED', @repository.find(1).attributes['title']
52
- end
53
-
54
- should "update the document with a script" do
55
- @repository.save Note.new(id: 1, title: 'Test')
56
-
57
- @repository.update 1, script: 'ctx._source.title = "UPDATED"'
58
- assert_equal 'UPDATED', @repository.find(1).attributes['title']
59
- end
60
-
61
- should "delete the object" do
62
- note = My::Note.new id: 1, title: 'Test'
63
- @repository.save note
64
-
65
- assert_not_nil @repository.find(1)
66
-
67
- @repository.delete(note)
68
- assert_raise(Elasticsearch::Persistence::Repository::DocumentNotFound) { @repository.find(1) }
69
- end
70
-
71
- should "create the index with correct mapping" do
72
- note = My::Note.new title: 'Testing'
73
- @repository.save note, refresh: true
74
-
75
- results = @repository.search query: { match: { title: 'Test' } }
76
- assert_equal 'Testing', results.first.attributes['title']
77
- end
78
- end
79
-
80
- end
81
- end
82
- end
@@ -1,116 +0,0 @@
1
- require 'test_helper'
2
-
3
- module Elasticsearch
4
- module Persistence
5
- class RepositoryDefaultClassIntegrationTest < Elasticsearch::Test::IntegrationTestCase
6
-
7
- class ::Note
8
- attr_reader :attributes
9
-
10
- def initialize(attributes={})
11
- @attributes = attributes
12
- end
13
-
14
- def to_hash
15
- @attributes
16
- end
17
- end
18
-
19
- context "The default repository class" do
20
- setup do
21
- @repository = Elasticsearch::Persistence::Repository.new
22
- @repository.client.cluster.health wait_for_status: 'yellow'
23
- end
24
-
25
- should "save the object with a custom ID and find it" do
26
- @repository.save Note.new(id: '1', title: 'Test')
27
-
28
- assert_equal 'Test', @repository.find(1).attributes['title']
29
- end
30
-
31
- should "save the object with an auto-generated ID and find it" do
32
- response = @repository.save Note.new(title: 'Test')
33
-
34
- assert_equal 'Test', @repository.find(response['_id']).attributes['title']
35
- end
36
-
37
- should "update the document" do
38
- @repository.save Note.new(id: 1, title: 'Test')
39
-
40
- @repository.update 1, type: 'note', doc: { title: 'UPDATED' }
41
- assert_equal 'UPDATED', @repository.find(1).attributes['title']
42
- end
43
-
44
- should "update the document with a script" do
45
- @repository.save Note.new(id: 1, title: 'Test')
46
-
47
- @repository.update 1, type: 'note', script: 'ctx._source.title = "UPDATED"'
48
- assert_equal 'UPDATED', @repository.find(1).attributes['title']
49
- end
50
-
51
- should "save the document with an upsert" do
52
- @repository.update 1, type: 'note', script: 'ctx._source.clicks += 1', upsert: { clicks: 1 }
53
- assert_equal 1, @repository.find(1).attributes['clicks']
54
- end
55
-
56
- should "delete an object" do
57
- note = Note.new(id: '1', title: 'Test')
58
-
59
- @repository.save(note)
60
- assert_not_nil @repository.find(1)
61
- @repository.delete(note)
62
- assert_raise(Elasticsearch::Persistence::Repository::DocumentNotFound) { @repository.find(1) }
63
- end
64
-
65
- should "find multiple objects" do
66
- (1..5).each { |i| @repository.save Note.new(id: i, title: "Test #{i}") }
67
-
68
- assert_equal 5, @repository.find(1, 2, 3, 4, 5).size
69
- assert_equal 5, @repository.find([1, 2, 3, 4, 5]).size
70
- end
71
-
72
- should "pass options to save and find" do
73
- note = Note.new(id: '1', title: 'Test')
74
- @repository.save note, routing: 'ABC'
75
-
76
- @repository.client.cluster.health level: 'indices', wait_for_status: 'yellow'
77
-
78
- assert_raise Elasticsearch::Persistence::Repository::DocumentNotFound do
79
- @repository.find(1, routing: 'DEF')
80
- end
81
-
82
- assert_nothing_raised do
83
- note = @repository.find(1, routing: 'ABC')
84
- assert_instance_of Note, note
85
- end
86
- end
87
-
88
- should "find notes with full text search" do
89
- @repository.save Note.new(title: 'Test')
90
- @repository.save Note.new(title: 'Test Test')
91
- @repository.save Note.new(title: 'Crust')
92
- @repository.client.indices.refresh index: @repository.index_name
93
-
94
- results = @repository.search 'test'
95
- assert_equal 2, results.size
96
-
97
- results = @repository.search query: { match: { title: 'Test' } }
98
- assert_equal 2, results.size
99
- end
100
-
101
- should "count notes" do
102
- @repository.save Note.new(title: 'Test')
103
- @repository.client.indices.refresh index: @repository.index_name
104
- assert_equal 1, @repository.count
105
- end
106
-
107
- should "save and find a plain hash" do
108
- @repository.save id: 1, title: 'Hash'
109
- result = @repository.find(1)
110
- assert_equal 'Hash', result['_source']['title']
111
- end
112
- end
113
-
114
- end
115
- end
116
- end