elasticsearch-model 0.1.9 → 7.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (145) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -2
  3. data/Gemfile +22 -0
  4. data/LICENSE.txt +199 -10
  5. data/README.md +96 -43
  6. data/Rakefile +49 -35
  7. data/elasticsearch-model.gemspec +53 -41
  8. data/examples/activerecord_article.rb +18 -1
  9. data/examples/activerecord_associations.rb +86 -17
  10. data/examples/activerecord_custom_analyzer.rb +152 -0
  11. data/examples/activerecord_mapping_completion.rb +33 -16
  12. data/examples/activerecord_mapping_edge_ngram.rb +118 -0
  13. data/examples/couchbase_article.rb +17 -0
  14. data/examples/datamapper_article.rb +28 -1
  15. data/examples/mongoid_article.rb +17 -0
  16. data/examples/ohm_article.rb +17 -0
  17. data/examples/riak_article.rb +17 -0
  18. data/gemfiles/3.0.gemfile +23 -1
  19. data/gemfiles/4.0.gemfile +25 -1
  20. data/gemfiles/5.0.gemfile +35 -0
  21. data/gemfiles/6.0.gemfile +36 -0
  22. data/lib/elasticsearch/model/adapter.rb +17 -0
  23. data/lib/elasticsearch/model/adapters/active_record.rb +31 -27
  24. data/lib/elasticsearch/model/adapters/default.rb +17 -0
  25. data/lib/elasticsearch/model/adapters/mongoid.rb +27 -3
  26. data/lib/elasticsearch/model/adapters/multiple.rb +29 -4
  27. data/lib/elasticsearch/model/callbacks.rb +17 -0
  28. data/lib/elasticsearch/model/client.rb +17 -0
  29. data/lib/elasticsearch/model/ext/active_record.rb +17 -0
  30. data/lib/elasticsearch/model/hash_wrapper.rb +32 -0
  31. data/lib/elasticsearch/model/importing.rb +61 -17
  32. data/lib/elasticsearch/model/indexing.rb +87 -49
  33. data/lib/elasticsearch/model/multimodel.rb +17 -0
  34. data/lib/elasticsearch/model/naming.rb +33 -2
  35. data/lib/elasticsearch/model/proxy.rb +61 -18
  36. data/lib/elasticsearch/model/response/aggregations.rb +55 -0
  37. data/lib/elasticsearch/model/response/base.rb +25 -3
  38. data/lib/elasticsearch/model/response/pagination/kaminari.rb +126 -0
  39. data/lib/elasticsearch/model/response/pagination/will_paginate.rb +112 -0
  40. data/lib/elasticsearch/model/response/pagination.rb +19 -192
  41. data/lib/elasticsearch/model/response/records.rb +17 -1
  42. data/lib/elasticsearch/model/response/result.rb +19 -2
  43. data/lib/elasticsearch/model/response/results.rb +17 -0
  44. data/lib/elasticsearch/model/response/suggestions.rb +20 -1
  45. data/lib/elasticsearch/model/response.rb +28 -10
  46. data/lib/elasticsearch/model/searching.rb +17 -0
  47. data/lib/elasticsearch/model/serializing.rb +17 -0
  48. data/lib/elasticsearch/model/version.rb +18 -1
  49. data/lib/elasticsearch/model.rb +36 -39
  50. data/spec/elasticsearch/model/adapter_spec.rb +136 -0
  51. data/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +351 -0
  52. data/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +395 -0
  53. data/spec/elasticsearch/model/adapters/active_record/dynamic_index_name_spec.rb +35 -0
  54. data/spec/elasticsearch/model/adapters/active_record/import_spec.rb +193 -0
  55. data/spec/elasticsearch/model/adapters/active_record/multi_model_spec.rb +127 -0
  56. data/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +55 -0
  57. data/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +332 -0
  58. data/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +92 -0
  59. data/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +78 -0
  60. data/spec/elasticsearch/model/adapters/active_record_spec.rb +224 -0
  61. data/spec/elasticsearch/model/adapters/default_spec.rb +58 -0
  62. data/spec/elasticsearch/model/adapters/mongoid/basic_spec.rb +284 -0
  63. data/spec/elasticsearch/model/adapters/mongoid/multi_model_spec.rb +83 -0
  64. data/spec/elasticsearch/model/adapters/mongoid_spec.rb +252 -0
  65. data/spec/elasticsearch/model/adapters/multiple_spec.rb +142 -0
  66. data/spec/elasticsearch/model/callbacks_spec.rb +50 -0
  67. data/spec/elasticsearch/model/client_spec.rb +83 -0
  68. data/spec/elasticsearch/model/hash_wrapper_spec.rb +29 -0
  69. data/spec/elasticsearch/model/importing_spec.rb +243 -0
  70. data/spec/elasticsearch/model/indexing_spec.rb +1014 -0
  71. data/spec/elasticsearch/model/module_spec.rb +94 -0
  72. data/spec/elasticsearch/model/multimodel_spec.rb +72 -0
  73. data/spec/elasticsearch/model/naming_spec.rb +203 -0
  74. data/spec/elasticsearch/model/proxy_spec.rb +124 -0
  75. data/spec/elasticsearch/model/response/aggregations_spec.rb +83 -0
  76. data/spec/elasticsearch/model/response/base_spec.rb +107 -0
  77. data/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +472 -0
  78. data/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +279 -0
  79. data/spec/elasticsearch/model/response/records_spec.rb +135 -0
  80. data/spec/elasticsearch/model/response/response_spec.rb +148 -0
  81. data/spec/elasticsearch/model/response/result_spec.rb +139 -0
  82. data/spec/elasticsearch/model/response/results_spec.rb +73 -0
  83. data/spec/elasticsearch/model/searching_search_request_spec.rb +129 -0
  84. data/spec/elasticsearch/model/searching_spec.rb +66 -0
  85. data/spec/elasticsearch/model/serializing_spec.rb +39 -0
  86. data/spec/spec_helper.rb +193 -0
  87. data/spec/support/app/answer.rb +50 -0
  88. data/spec/support/app/article.rb +39 -0
  89. data/spec/support/app/article_for_pagination.rb +29 -0
  90. data/spec/support/app/article_no_type.rb +37 -0
  91. data/spec/support/app/article_with_custom_serialization.rb +30 -0
  92. data/spec/support/app/article_with_dynamic_index_name.rb +32 -0
  93. data/spec/support/app/author.rb +26 -0
  94. data/spec/support/app/authorship.rb +21 -0
  95. data/spec/support/app/category.rb +20 -0
  96. data/spec/support/app/comment.rb +20 -0
  97. data/spec/support/app/episode.rb +28 -0
  98. data/spec/support/app/image.rb +36 -0
  99. data/spec/support/app/import_article.rb +29 -0
  100. data/spec/support/app/mongoid_article.rb +38 -0
  101. data/spec/support/app/namespaced_book.rb +27 -0
  102. data/spec/support/app/parent_and_child_searchable.rb +41 -0
  103. data/spec/support/app/post.rb +31 -0
  104. data/spec/support/app/question.rb +44 -0
  105. data/spec/support/app/searchable.rb +65 -0
  106. data/spec/support/app/series.rb +28 -0
  107. data/spec/support/app.rb +46 -0
  108. data/spec/support/model.json +1 -0
  109. data/{test → spec}/support/model.yml +0 -0
  110. metadata +175 -121
  111. data/test/integration/active_record_associations_parent_child.rb +0 -139
  112. data/test/integration/active_record_associations_test.rb +0 -326
  113. data/test/integration/active_record_basic_test.rb +0 -234
  114. data/test/integration/active_record_custom_serialization_test.rb +0 -62
  115. data/test/integration/active_record_import_test.rb +0 -109
  116. data/test/integration/active_record_namespaced_model_test.rb +0 -49
  117. data/test/integration/active_record_pagination_test.rb +0 -145
  118. data/test/integration/dynamic_index_name_test.rb +0 -47
  119. data/test/integration/mongoid_basic_test.rb +0 -177
  120. data/test/integration/multiple_models_test.rb +0 -172
  121. data/test/support/model.json +0 -1
  122. data/test/test_helper.rb +0 -93
  123. data/test/unit/adapter_active_record_test.rb +0 -157
  124. data/test/unit/adapter_default_test.rb +0 -41
  125. data/test/unit/adapter_mongoid_test.rb +0 -104
  126. data/test/unit/adapter_multiple_test.rb +0 -106
  127. data/test/unit/adapter_test.rb +0 -69
  128. data/test/unit/callbacks_test.rb +0 -31
  129. data/test/unit/client_test.rb +0 -27
  130. data/test/unit/importing_test.rb +0 -203
  131. data/test/unit/indexing_test.rb +0 -650
  132. data/test/unit/module_test.rb +0 -57
  133. data/test/unit/multimodel_test.rb +0 -38
  134. data/test/unit/naming_test.rb +0 -103
  135. data/test/unit/proxy_test.rb +0 -100
  136. data/test/unit/response_base_test.rb +0 -40
  137. data/test/unit/response_pagination_kaminari_test.rb +0 -433
  138. data/test/unit/response_pagination_will_paginate_test.rb +0 -398
  139. data/test/unit/response_records_test.rb +0 -91
  140. data/test/unit/response_result_test.rb +0 -90
  141. data/test/unit/response_results_test.rb +0 -31
  142. data/test/unit/response_test.rb +0 -104
  143. data/test/unit/searching_search_request_test.rb +0 -78
  144. data/test/unit/searching_test.rb +0 -41
  145. data/test/unit/serializing_test.rb +0 -17
@@ -0,0 +1,351 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ require 'spec_helper'
19
+
20
+ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
21
+
22
+ before(:all) do
23
+ ActiveRecord::Schema.define(version: 1) do
24
+ create_table :categories do |t|
25
+ t.string :title
26
+ t.timestamps null: false
27
+ end
28
+
29
+ create_table :categories_posts do |t|
30
+ t.references :post, :category
31
+ end
32
+
33
+ create_table :authors do |t|
34
+ t.string :first_name, :last_name
35
+ t.timestamps null: false
36
+ end
37
+
38
+ create_table :authorships do |t|
39
+ t.string :first_name, :last_name
40
+ t.references :post
41
+ t.references :author
42
+ t.timestamps null: false
43
+ end
44
+
45
+ create_table :comments do |t|
46
+ t.string :text
47
+ t.string :author
48
+ t.references :post
49
+ t.timestamps null: false
50
+ end
51
+
52
+ add_index(:comments, :post_id) unless index_exists?(:comments, :post_id)
53
+
54
+ create_table :posts do |t|
55
+ t.string :title
56
+ t.text :text
57
+ t.boolean :published
58
+ t.timestamps null: false
59
+ end
60
+ end
61
+
62
+ Comment.__send__ :include, Elasticsearch::Model
63
+ Comment.__send__ :include, Elasticsearch::Model::Callbacks
64
+ end
65
+
66
+ before do
67
+ clear_tables(:categories, :categories_posts, :authors, :authorships, :comments, :posts)
68
+ clear_indices(Post)
69
+ Post.__elasticsearch__.create_index!(force: true)
70
+ Comment.__elasticsearch__.create_index!(force: true)
71
+ end
72
+
73
+ after do
74
+ clear_tables(Post, Category)
75
+ clear_indices(Post)
76
+ end
77
+
78
+ context 'when a document is created' do
79
+
80
+ before do
81
+ Post.create!(title: 'Test')
82
+ Post.create!(title: 'Testing Coding')
83
+ Post.create!(title: 'Coding')
84
+ Post.__elasticsearch__.refresh_index!
85
+ end
86
+
87
+ let(:search_result) do
88
+ Post.search('title:test')
89
+ end
90
+
91
+ it 'indexes the document' do
92
+ expect(search_result.results.size).to eq(2)
93
+ expect(search_result.results.first.title).to eq('Test')
94
+ expect(search_result.records.size).to eq(2)
95
+ expect(search_result.records.first.title).to eq('Test')
96
+ end
97
+ end
98
+
99
+ describe 'has_many_and_belongs_to association' do
100
+
101
+ context 'when an association is updated' do
102
+
103
+ before do
104
+ post.categories = [category_a, category_b]
105
+ Post.__elasticsearch__.refresh_index!
106
+ end
107
+
108
+ let(:category_a) do
109
+ Category.where(title: "One").first_or_create!
110
+ end
111
+
112
+ let(:category_b) do
113
+ Category.where(title: "Two").first_or_create!
114
+ end
115
+
116
+ let(:post) do
117
+ Post.create! title: "First Post", text: "This is the first post..."
118
+ end
119
+
120
+ let(:search_result) do
121
+ Post.search(query: {
122
+ bool: {
123
+ must: {
124
+ multi_match: {
125
+ fields: ['title'],
126
+ query: 'first'
127
+ }
128
+ },
129
+ filter: {
130
+ terms: {
131
+ categories: ['One']
132
+ }
133
+ }
134
+ }
135
+ } )
136
+ end
137
+
138
+ it 'applies the update with' do
139
+ expect(search_result.results.size).to eq(1)
140
+ expect(search_result.results.first.title).to eq('First Post')
141
+ expect(search_result.records.size).to eq(1)
142
+ expect(search_result.records.first.title).to eq('First Post')
143
+ end
144
+ end
145
+
146
+ context 'when an association is deleted' do
147
+
148
+ before do
149
+ post.categories = [category_a, category_b]
150
+ post.categories = [category_b]
151
+ Post.__elasticsearch__.refresh_index!
152
+ end
153
+
154
+ let(:category_a) do
155
+ Category.where(title: "One").first_or_create!
156
+ end
157
+
158
+ let(:category_b) do
159
+ Category.where(title: "Two").first_or_create!
160
+ end
161
+
162
+ let(:post) do
163
+ Post.create! title: "First Post", text: "This is the first post..."
164
+ end
165
+
166
+ let(:search_result) do
167
+ Post.search(query: {
168
+ bool: {
169
+ must: {
170
+ multi_match: {
171
+ fields: ['title'],
172
+ query: 'first'
173
+ }
174
+ },
175
+ filter: {
176
+ terms: {
177
+ categories: ['One']
178
+ }
179
+ }
180
+ }
181
+ } )
182
+ end
183
+
184
+ it 'applies the update with a reindex' do
185
+ expect(search_result.results.size).to eq(0)
186
+ expect(search_result.records.size).to eq(0)
187
+ end
188
+ end
189
+ end
190
+
191
+ describe 'has_many through association' do
192
+
193
+ context 'when the association is updated' do
194
+
195
+ before do
196
+ author_a = Author.where(first_name: "John", last_name: "Smith").first_or_create!
197
+ author_b = Author.where(first_name: "Mary", last_name: "Smith").first_or_create!
198
+ author_c = Author.where(first_name: "Kobe", last_name: "Griss").first_or_create!
199
+
200
+ # Create posts
201
+ post_1 = Post.create!(title: "First Post", text: "This is the first post...")
202
+ post_2 = Post.create!(title: "Second Post", text: "This is the second post...")
203
+ post_3 = Post.create!(title: "Third Post", text: "This is the third post...")
204
+
205
+ # Assign authors
206
+ post_1.authors = [author_a, author_b]
207
+ post_2.authors = [author_a]
208
+ post_3.authors = [author_c]
209
+
210
+ Post.__elasticsearch__.refresh_index!
211
+ end
212
+
213
+ context 'if active record is at least 4' do
214
+
215
+ let(:search_result) do
216
+ Post.search('authors.full_name:john')
217
+ end
218
+
219
+ it 'applies the update', if: active_record_at_least_4? do
220
+ expect(search_result.results.size).to eq(2)
221
+ expect(search_result.records.size).to eq(2)
222
+ end
223
+ end
224
+
225
+ context 'if active record is less than 4' do
226
+
227
+ let(:search_result) do
228
+ Post.search('authors.author.full_name:john')
229
+ end
230
+
231
+ it 'applies the update', if: !active_record_at_least_4? do
232
+ expect(search_result.results.size).to eq(2)
233
+ expect(search_result.records.size).to eq(2)
234
+ end
235
+ end
236
+ end
237
+
238
+ context 'when an association is added', if: active_record_at_least_4? do
239
+
240
+ before do
241
+ author_a = Author.where(first_name: "John", last_name: "Smith").first_or_create!
242
+ author_b = Author.where(first_name: "Mary", last_name: "Smith").first_or_create!
243
+
244
+ # Create posts
245
+ post_1 = Post.create!(title: "First Post", text: "This is the first post...")
246
+
247
+ # Assign authors
248
+ post_1.authors = [author_a]
249
+ post_1.authors << author_b
250
+ Post.__elasticsearch__.refresh_index!
251
+ end
252
+
253
+ let(:search_result) do
254
+ Post.search('authors.full_name:john')
255
+ end
256
+
257
+ it 'adds the association' do
258
+ expect(search_result.results.size).to eq(1)
259
+ expect(search_result.records.size).to eq(1)
260
+ end
261
+ end
262
+ end
263
+
264
+ describe 'has_many association' do
265
+
266
+ context 'when an association is added', if: active_record_at_least_4? do
267
+
268
+ before do
269
+ # Create posts
270
+ post_1 = Post.create!(title: "First Post", text: "This is the first post...")
271
+ post_2 = Post.create!(title: "Second Post", text: "This is the second post...")
272
+
273
+ # Add comments
274
+ post_1.comments.create!(author: 'John', text: 'Excellent')
275
+ post_1.comments.create!(author: 'Abby', text: 'Good')
276
+
277
+ post_2.comments.create!(author: 'John', text: 'Terrible')
278
+
279
+ post_1.comments.create!(author: 'John', text: 'Or rather just good...')
280
+ Post.__elasticsearch__.refresh_index!
281
+ end
282
+
283
+ let(:search_result) do
284
+ Post.search(query: {
285
+ nested: {
286
+ path: 'comments',
287
+ query: {
288
+ bool: {
289
+ must: [
290
+ { match: { 'comments.author' => 'john' } },
291
+ { match: { 'comments.text' => 'good' } }
292
+ ]
293
+ }
294
+ }
295
+ }
296
+ })
297
+ end
298
+
299
+ it 'adds the association' do
300
+ expect(search_result.results.size).to eq(1)
301
+ end
302
+ end
303
+ end
304
+
305
+ describe '#touch' do
306
+
307
+ context 'when a touch callback is defined on the model' do
308
+
309
+ before do
310
+ # Create categories
311
+ category_a = Category.where(title: "One").first_or_create!
312
+
313
+ # Create post
314
+ post = Post.create!(title: "First Post", text: "This is the first post...")
315
+
316
+ # Assign category
317
+ post.categories << category_a
318
+ category_a.update_attribute(:title, "Updated")
319
+ category_a.posts.each { |p| p.touch }
320
+
321
+ Post.__elasticsearch__.refresh_index!
322
+ end
323
+
324
+ it 'executes the callback after #touch' do
325
+ expect(Post.search('categories:One').size).to eq(0)
326
+ expect(Post.search('categories:Updated').size).to eq(1)
327
+ end
328
+ end
329
+ end
330
+
331
+ describe '#includes' do
332
+
333
+ before do
334
+ post_1 = Post.create(title: 'One')
335
+ post_2 = Post.create(title: 'Two')
336
+ post_1.comments.create(text: 'First comment')
337
+ post_2.comments.create(text: 'Second comment')
338
+
339
+ Comment.__elasticsearch__.refresh_index!
340
+ end
341
+
342
+ let(:search_result) do
343
+ Comment.search('first').records(includes: :post)
344
+ end
345
+
346
+ it 'eager loads associations' do
347
+ expect(search_result.first.association(:post)).to be_loaded
348
+ expect(search_result.first.post.title).to eq('One')
349
+ end
350
+ end
351
+ end