elasticsearch-model 5.1.0 → 6.1.0
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/Gemfile +5 -0
- data/README.md +18 -11
- data/Rakefile +27 -36
- data/elasticsearch-model.gemspec +5 -5
- data/examples/activerecord_custom_analyzer.rb +135 -0
- data/examples/activerecord_mapping_completion.rb +3 -18
- data/examples/datamapper_article.rb +11 -1
- data/gemfiles/3.0.gemfile +6 -1
- data/gemfiles/4.0.gemfile +7 -1
- data/gemfiles/5.0.gemfile +7 -1
- data/lib/elasticsearch/model/adapters/active_record.rb +7 -23
- data/lib/elasticsearch/model/adapters/mongoid.rb +10 -3
- data/lib/elasticsearch/model/importing.rb +1 -1
- data/lib/elasticsearch/model/indexing.rb +6 -4
- data/lib/elasticsearch/model/naming.rb +9 -2
- data/lib/elasticsearch/model/response/aggregations.rb +1 -1
- data/lib/elasticsearch/model/response/base.rb +3 -2
- data/lib/elasticsearch/model/response/pagination/kaminari.rb +109 -0
- data/lib/elasticsearch/model/response/pagination/will_paginate.rb +95 -0
- data/lib/elasticsearch/model/response/pagination.rb +2 -192
- data/lib/elasticsearch/model/response/result.rb +1 -1
- data/lib/elasticsearch/model/response/suggestions.rb +1 -1
- data/lib/elasticsearch/model/response.rb +11 -10
- data/lib/elasticsearch/model/version.rb +1 -1
- data/lib/elasticsearch/model.rb +15 -8
- data/spec/elasticsearch/model/adapter_spec.rb +119 -0
- data/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +334 -0
- data/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +340 -0
- data/spec/elasticsearch/model/adapters/active_record/dynamic_index_name_spec.rb +18 -0
- data/spec/elasticsearch/model/adapters/active_record/import_spec.rb +187 -0
- data/spec/elasticsearch/model/adapters/active_record/multi_model_spec.rb +110 -0
- data/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +38 -0
- data/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +315 -0
- data/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +75 -0
- data/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +61 -0
- data/spec/elasticsearch/model/adapters/active_record_spec.rb +207 -0
- data/spec/elasticsearch/model/adapters/default_spec.rb +41 -0
- data/spec/elasticsearch/model/adapters/mongoid/basic_spec.rb +267 -0
- data/spec/elasticsearch/model/adapters/mongoid/multi_model_spec.rb +66 -0
- data/spec/elasticsearch/model/adapters/mongoid_spec.rb +235 -0
- data/spec/elasticsearch/model/adapters/multiple_spec.rb +125 -0
- data/spec/elasticsearch/model/callbacks_spec.rb +33 -0
- data/spec/elasticsearch/model/client_spec.rb +66 -0
- data/spec/elasticsearch/model/hash_wrapper_spec.rb +12 -0
- data/spec/elasticsearch/model/importing_spec.rb +214 -0
- data/spec/elasticsearch/model/indexing_spec.rb +918 -0
- data/spec/elasticsearch/model/module_spec.rb +101 -0
- data/spec/elasticsearch/model/multimodel_spec.rb +55 -0
- data/spec/elasticsearch/model/naming_inheritance_spec.rb +184 -0
- data/spec/elasticsearch/model/naming_spec.rb +186 -0
- data/spec/elasticsearch/model/proxy_spec.rb +107 -0
- data/spec/elasticsearch/model/response/aggregations_spec.rb +66 -0
- data/spec/elasticsearch/model/response/base_spec.rb +90 -0
- data/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +410 -0
- data/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +262 -0
- data/spec/elasticsearch/model/response/records_spec.rb +118 -0
- data/spec/elasticsearch/model/response/response_spec.rb +131 -0
- data/spec/elasticsearch/model/response/result_spec.rb +122 -0
- data/spec/elasticsearch/model/response/results_spec.rb +56 -0
- data/spec/elasticsearch/model/searching_search_request_spec.rb +112 -0
- data/spec/elasticsearch/model/searching_spec.rb +49 -0
- data/spec/elasticsearch/model/serializing_spec.rb +22 -0
- data/spec/spec_helper.rb +161 -0
- data/spec/support/app/answer.rb +33 -0
- data/spec/support/app/article.rb +22 -0
- data/spec/support/app/article_for_pagination.rb +12 -0
- data/spec/support/app/article_with_custom_serialization.rb +13 -0
- data/spec/support/app/article_with_dynamic_index_name.rb +15 -0
- data/spec/support/app/author.rb +9 -0
- data/spec/support/app/authorship.rb +4 -0
- data/spec/support/app/category.rb +3 -0
- data/spec/support/app/comment.rb +3 -0
- data/spec/support/app/episode.rb +11 -0
- data/spec/support/app/image.rb +19 -0
- data/spec/support/app/import_article.rb +12 -0
- data/spec/support/app/mongoid_article.rb +21 -0
- data/spec/support/app/namespaced_book.rb +10 -0
- data/spec/support/app/parent_and_child_searchable.rb +24 -0
- data/spec/support/app/post.rb +14 -0
- data/spec/support/app/question.rb +27 -0
- data/spec/support/app/searchable.rb +48 -0
- data/spec/support/app/series.rb +11 -0
- data/spec/support/app.rb +21 -0
- data/spec/support/model.json +1 -0
- metadata +134 -90
- data/test/integration/active_record_associations_parent_child_test.rb +0 -147
- data/test/integration/active_record_associations_test.rb +0 -339
- data/test/integration/active_record_basic_test.rb +0 -251
- data/test/integration/active_record_custom_serialization_test.rb +0 -67
- data/test/integration/active_record_import_test.rb +0 -115
- data/test/integration/active_record_namespaced_model_test.rb +0 -54
- data/test/integration/active_record_pagination_test.rb +0 -149
- data/test/integration/dynamic_index_name_test.rb +0 -52
- data/test/integration/mongoid_basic_test.rb +0 -176
- data/test/integration/multiple_models_test.rb +0 -176
- data/test/support/model.json +0 -1
- data/test/test_helper.rb +0 -92
- data/test/unit/adapter_active_record_test.rb +0 -157
- data/test/unit/adapter_default_test.rb +0 -41
- data/test/unit/adapter_mongoid_test.rb +0 -104
- data/test/unit/adapter_multiple_test.rb +0 -106
- data/test/unit/adapter_test.rb +0 -69
- data/test/unit/callbacks_test.rb +0 -31
- data/test/unit/client_test.rb +0 -27
- data/test/unit/hash_wrapper_test.rb +0 -13
- data/test/unit/importing_test.rb +0 -203
- data/test/unit/indexing_test.rb +0 -687
- data/test/unit/module_test.rb +0 -68
- data/test/unit/multimodel_test.rb +0 -38
- data/test/unit/naming_inheritance_test.rb +0 -94
- data/test/unit/naming_test.rb +0 -103
- data/test/unit/proxy_test.rb +0 -98
- data/test/unit/response_aggregations_test.rb +0 -46
- data/test/unit/response_base_test.rb +0 -40
- data/test/unit/response_pagination_kaminari_test.rb +0 -433
- data/test/unit/response_pagination_will_paginate_test.rb +0 -398
- data/test/unit/response_records_test.rb +0 -91
- data/test/unit/response_result_test.rb +0 -90
- data/test/unit/response_results_test.rb +0 -31
- data/test/unit/response_test.rb +0 -104
- data/test/unit/searching_search_request_test.rb +0 -78
- data/test/unit/searching_test.rb +0 -41
- data/test/unit/serializing_test.rb +0 -17
- /data/{test → spec}/support/model.yml +0 -0
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
require 'active_record'
|
|
3
|
-
|
|
4
|
-
# Needed for ActiveRecord 3.x ?
|
|
5
|
-
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ":memory:" ) unless ActiveRecord::Base.connected?
|
|
6
|
-
|
|
7
|
-
::ActiveRecord::Base.raise_in_transactional_callbacks = true if ::ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks) && ::ActiveRecord::VERSION::MAJOR.to_s < '5'
|
|
8
|
-
|
|
9
|
-
module Elasticsearch
|
|
10
|
-
module Model
|
|
11
|
-
class ActiveRecordAssociationsIntegrationTest < Elasticsearch::Test::IntegrationTestCase
|
|
12
|
-
|
|
13
|
-
# ----- Search integration via Concern module -----------------------------------------------------
|
|
14
|
-
|
|
15
|
-
module Searchable
|
|
16
|
-
extend ActiveSupport::Concern
|
|
17
|
-
|
|
18
|
-
included do
|
|
19
|
-
include Elasticsearch::Model
|
|
20
|
-
include Elasticsearch::Model::Callbacks
|
|
21
|
-
|
|
22
|
-
# Set up the mapping
|
|
23
|
-
#
|
|
24
|
-
settings index: { number_of_shards: 1, number_of_replicas: 0 } do
|
|
25
|
-
mapping do
|
|
26
|
-
indexes :title, analyzer: 'snowball'
|
|
27
|
-
indexes :created_at, type: 'date'
|
|
28
|
-
|
|
29
|
-
indexes :authors do
|
|
30
|
-
indexes :first_name
|
|
31
|
-
indexes :last_name
|
|
32
|
-
indexes :full_name, type: 'text' do
|
|
33
|
-
indexes :raw, type: 'keyword'
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
indexes :categories, type: 'keyword'
|
|
38
|
-
|
|
39
|
-
indexes :comments, type: 'nested' do
|
|
40
|
-
indexes :text
|
|
41
|
-
indexes :author
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# Customize the JSON serialization for Elasticsearch
|
|
47
|
-
#
|
|
48
|
-
def as_indexed_json(options={})
|
|
49
|
-
{
|
|
50
|
-
title: title,
|
|
51
|
-
text: text,
|
|
52
|
-
categories: categories.map(&:title),
|
|
53
|
-
authors: authors.as_json(methods: [:full_name], only: [:full_name, :first_name, :last_name]),
|
|
54
|
-
comments: comments.as_json(only: [:text, :author])
|
|
55
|
-
}
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Update document in the index after touch
|
|
59
|
-
#
|
|
60
|
-
after_touch() { __elasticsearch__.index_document }
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
context "ActiveRecord associations" do
|
|
65
|
-
setup do
|
|
66
|
-
|
|
67
|
-
# ----- Schema definition ---------------------------------------------------------------
|
|
68
|
-
|
|
69
|
-
ActiveRecord::Schema.define(version: 1) do
|
|
70
|
-
create_table :categories do |t|
|
|
71
|
-
t.string :title
|
|
72
|
-
t.timestamps null: false
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
create_table :categories_posts, id: false do |t|
|
|
76
|
-
t.references :post, :category
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
create_table :authors do |t|
|
|
80
|
-
t.string :first_name, :last_name
|
|
81
|
-
t.timestamps null: false
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
create_table :authorships do |t|
|
|
85
|
-
t.string :first_name, :last_name
|
|
86
|
-
t.references :post
|
|
87
|
-
t.references :author
|
|
88
|
-
t.timestamps null: false
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
create_table :comments do |t|
|
|
92
|
-
t.string :text
|
|
93
|
-
t.string :author
|
|
94
|
-
t.references :post
|
|
95
|
-
t.timestamps null: false
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
add_index(:comments, :post_id) unless index_exists?(:comments, :post_id)
|
|
99
|
-
|
|
100
|
-
create_table :posts do |t|
|
|
101
|
-
t.string :title
|
|
102
|
-
t.text :text
|
|
103
|
-
t.boolean :published
|
|
104
|
-
t.timestamps null: false
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
# ----- Models definition -------------------------------------------------------------------------
|
|
109
|
-
|
|
110
|
-
class Category < ActiveRecord::Base
|
|
111
|
-
has_and_belongs_to_many :posts
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
class Author < ActiveRecord::Base
|
|
115
|
-
has_many :authorships
|
|
116
|
-
|
|
117
|
-
after_update { self.authorships.each(&:touch) }
|
|
118
|
-
|
|
119
|
-
def full_name
|
|
120
|
-
[first_name, last_name].compact.join(' ')
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
class Authorship < ActiveRecord::Base
|
|
125
|
-
belongs_to :author
|
|
126
|
-
belongs_to :post, touch: true
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
class Comment < ActiveRecord::Base
|
|
130
|
-
belongs_to :post, touch: true
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
class Post < ActiveRecord::Base
|
|
134
|
-
has_and_belongs_to_many :categories, after_add: [ lambda { |a,c| a.__elasticsearch__.index_document } ],
|
|
135
|
-
after_remove: [ lambda { |a,c| a.__elasticsearch__.index_document } ]
|
|
136
|
-
has_many :authorships
|
|
137
|
-
has_many :authors, through: :authorships,
|
|
138
|
-
after_add: [ lambda { |a,c| a.__elasticsearch__.index_document } ],
|
|
139
|
-
after_remove: [ lambda { |a,c| a.__elasticsearch__.index_document } ]
|
|
140
|
-
has_many :comments, after_add: [ lambda { |a,c| a.__elasticsearch__.index_document } ],
|
|
141
|
-
after_remove: [ lambda { |a,c| a.__elasticsearch__.index_document } ]
|
|
142
|
-
|
|
143
|
-
after_touch() { __elasticsearch__.index_document }
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# Include the search integration
|
|
147
|
-
#
|
|
148
|
-
Post.__send__ :include, Searchable
|
|
149
|
-
Comment.__send__ :include, Elasticsearch::Model
|
|
150
|
-
Comment.__send__ :include, Elasticsearch::Model::Callbacks
|
|
151
|
-
|
|
152
|
-
# ----- Reset the indices -----------------------------------------------------------------
|
|
153
|
-
|
|
154
|
-
Post.delete_all
|
|
155
|
-
Post.__elasticsearch__.create_index! force: true
|
|
156
|
-
|
|
157
|
-
Comment.delete_all
|
|
158
|
-
Comment.__elasticsearch__.create_index! force: true
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
should "index and find a document" do
|
|
162
|
-
Post.create! title: 'Test'
|
|
163
|
-
Post.create! title: 'Testing Coding'
|
|
164
|
-
Post.create! title: 'Coding'
|
|
165
|
-
Post.__elasticsearch__.refresh_index!
|
|
166
|
-
|
|
167
|
-
response = Post.search('title:test')
|
|
168
|
-
|
|
169
|
-
assert_equal 2, response.results.size
|
|
170
|
-
assert_equal 2, response.records.size
|
|
171
|
-
|
|
172
|
-
assert_equal 'Test', response.results.first.title
|
|
173
|
-
assert_equal 'Test', response.records.first.title
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
should "reindex a document after categories are changed" do
|
|
177
|
-
# Create categories
|
|
178
|
-
category_a = Category.where(title: "One").first_or_create!
|
|
179
|
-
category_b = Category.where(title: "Two").first_or_create!
|
|
180
|
-
|
|
181
|
-
# Create post
|
|
182
|
-
post = Post.create! title: "First Post", text: "This is the first post..."
|
|
183
|
-
|
|
184
|
-
# Assign categories
|
|
185
|
-
post.categories = [category_a, category_b]
|
|
186
|
-
|
|
187
|
-
Post.__elasticsearch__.refresh_index!
|
|
188
|
-
|
|
189
|
-
query = { query: {
|
|
190
|
-
bool: {
|
|
191
|
-
must: {
|
|
192
|
-
multi_match: {
|
|
193
|
-
fields: ['title'],
|
|
194
|
-
query: 'first'
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
filter: {
|
|
198
|
-
terms: {
|
|
199
|
-
categories: ['One']
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
response = Post.search query
|
|
207
|
-
|
|
208
|
-
assert_equal 1, response.results.size
|
|
209
|
-
assert_equal 1, response.records.size
|
|
210
|
-
|
|
211
|
-
# Remove category "One"
|
|
212
|
-
post.categories = [category_b]
|
|
213
|
-
|
|
214
|
-
Post.__elasticsearch__.refresh_index!
|
|
215
|
-
response = Post.search query
|
|
216
|
-
|
|
217
|
-
assert_equal 0, response.results.size
|
|
218
|
-
assert_equal 0, response.records.size
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
should "reindex a document after authors are changed" do
|
|
222
|
-
# Create authors
|
|
223
|
-
author_a = Author.where(first_name: "John", last_name: "Smith").first_or_create!
|
|
224
|
-
author_b = Author.where(first_name: "Mary", last_name: "Smith").first_or_create!
|
|
225
|
-
author_c = Author.where(first_name: "Kobe", last_name: "Griss").first_or_create!
|
|
226
|
-
|
|
227
|
-
# Create posts
|
|
228
|
-
post_1 = Post.create! title: "First Post", text: "This is the first post..."
|
|
229
|
-
post_2 = Post.create! title: "Second Post", text: "This is the second post..."
|
|
230
|
-
post_3 = Post.create! title: "Third Post", text: "This is the third post..."
|
|
231
|
-
|
|
232
|
-
# Assign authors
|
|
233
|
-
post_1.authors = [author_a, author_b]
|
|
234
|
-
post_2.authors = [author_a]
|
|
235
|
-
post_3.authors = [author_c]
|
|
236
|
-
|
|
237
|
-
Post.__elasticsearch__.refresh_index!
|
|
238
|
-
|
|
239
|
-
response = Post.search 'authors.full_name:john'
|
|
240
|
-
|
|
241
|
-
assert_equal 2, response.results.size
|
|
242
|
-
assert_equal 2, response.records.size
|
|
243
|
-
|
|
244
|
-
post_3.authors << author_a
|
|
245
|
-
|
|
246
|
-
Post.__elasticsearch__.refresh_index!
|
|
247
|
-
|
|
248
|
-
response = Post.search 'authors.full_name:john'
|
|
249
|
-
|
|
250
|
-
assert_equal 3, response.results.size
|
|
251
|
-
assert_equal 3, response.records.size
|
|
252
|
-
end if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 4
|
|
253
|
-
|
|
254
|
-
should "reindex a document after comments are added" do
|
|
255
|
-
# Create posts
|
|
256
|
-
post_1 = Post.create! title: "First Post", text: "This is the first post..."
|
|
257
|
-
post_2 = Post.create! title: "Second Post", text: "This is the second post..."
|
|
258
|
-
|
|
259
|
-
# Add comments
|
|
260
|
-
post_1.comments.create! author: 'John', text: 'Excellent'
|
|
261
|
-
post_1.comments.create! author: 'Abby', text: 'Good'
|
|
262
|
-
|
|
263
|
-
post_2.comments.create! author: 'John', text: 'Terrible'
|
|
264
|
-
|
|
265
|
-
Post.__elasticsearch__.refresh_index!
|
|
266
|
-
|
|
267
|
-
response = Post.search 'comments.author:john AND comments.text:good'
|
|
268
|
-
assert_equal 0, response.results.size
|
|
269
|
-
|
|
270
|
-
# Add comment
|
|
271
|
-
post_1.comments.create! author: 'John', text: 'Or rather just good...'
|
|
272
|
-
|
|
273
|
-
Post.__elasticsearch__.refresh_index!
|
|
274
|
-
|
|
275
|
-
response = Post.search 'comments.author:john AND comments.text:good'
|
|
276
|
-
assert_equal 0, response.results.size
|
|
277
|
-
|
|
278
|
-
response = Post.search \
|
|
279
|
-
query: {
|
|
280
|
-
nested: {
|
|
281
|
-
path: 'comments',
|
|
282
|
-
query: {
|
|
283
|
-
bool: {
|
|
284
|
-
must: [
|
|
285
|
-
{ match: { 'comments.author' => 'john' } },
|
|
286
|
-
{ match: { 'comments.text' => 'good' } }
|
|
287
|
-
]
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
assert_equal 1, response.results.size
|
|
294
|
-
end if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 4
|
|
295
|
-
|
|
296
|
-
should "reindex a document after Post#touch" do
|
|
297
|
-
# Create categories
|
|
298
|
-
category_a = Category.where(title: "One").first_or_create!
|
|
299
|
-
|
|
300
|
-
# Create post
|
|
301
|
-
post = Post.create! title: "First Post", text: "This is the first post..."
|
|
302
|
-
|
|
303
|
-
# Assign category
|
|
304
|
-
post.categories << category_a
|
|
305
|
-
|
|
306
|
-
Post.__elasticsearch__.refresh_index!
|
|
307
|
-
|
|
308
|
-
assert_equal 1, Post.search('categories:One').size
|
|
309
|
-
|
|
310
|
-
# Update category
|
|
311
|
-
category_a.update_attribute :title, "Updated"
|
|
312
|
-
|
|
313
|
-
# Trigger touch on posts in category
|
|
314
|
-
category_a.posts.each { |p| p.touch }
|
|
315
|
-
|
|
316
|
-
Post.__elasticsearch__.refresh_index!
|
|
317
|
-
|
|
318
|
-
assert_equal 0, Post.search('categories:One').size
|
|
319
|
-
assert_equal 1, Post.search('categories:Updated').size
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
should "eagerly load associated records" do
|
|
323
|
-
post_1 = Post.create(title: 'One')
|
|
324
|
-
post_2 = Post.create(title: 'Two')
|
|
325
|
-
post_1.comments.create text: 'First comment'
|
|
326
|
-
post_1.comments.create text: 'Second comment'
|
|
327
|
-
|
|
328
|
-
Comment.__elasticsearch__.refresh_index!
|
|
329
|
-
|
|
330
|
-
records = Comment.search('first').records(includes: :post)
|
|
331
|
-
|
|
332
|
-
assert records.first.association(:post).loaded?, "The associated Post should be eagerly loaded"
|
|
333
|
-
assert_equal 'One', records.first.post.title
|
|
334
|
-
end
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
end
|
|
338
|
-
end
|
|
339
|
-
end
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
require 'active_record'
|
|
3
|
-
|
|
4
|
-
puts "ActiveRecord #{ActiveRecord::VERSION::STRING}", '-'*80
|
|
5
|
-
|
|
6
|
-
# Needed for ActiveRecord 3.x ?
|
|
7
|
-
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ":memory:" ) unless ActiveRecord::Base.connected?
|
|
8
|
-
|
|
9
|
-
::ActiveRecord::Base.raise_in_transactional_callbacks = true if ::ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks) && ::ActiveRecord::VERSION::MAJOR.to_s < '5'
|
|
10
|
-
|
|
11
|
-
module Elasticsearch
|
|
12
|
-
module Model
|
|
13
|
-
class ActiveRecordBasicIntegrationTest < Elasticsearch::Test::IntegrationTestCase
|
|
14
|
-
|
|
15
|
-
class ::Article < ActiveRecord::Base
|
|
16
|
-
include Elasticsearch::Model
|
|
17
|
-
include Elasticsearch::Model::Callbacks
|
|
18
|
-
|
|
19
|
-
settings index: { number_of_shards: 1, number_of_replicas: 0 } do
|
|
20
|
-
mapping do
|
|
21
|
-
indexes :title, type: 'text', analyzer: 'snowball'
|
|
22
|
-
indexes :body, type: 'text'
|
|
23
|
-
indexes :clicks, type: 'integer'
|
|
24
|
-
indexes :created_at, type: 'date'
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def as_indexed_json(options = {})
|
|
29
|
-
attributes
|
|
30
|
-
.symbolize_keys
|
|
31
|
-
.slice(:title, :body, :clicks, :created_at)
|
|
32
|
-
.merge(suggest_title: title)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
context "ActiveRecord basic integration" do
|
|
37
|
-
setup do
|
|
38
|
-
ActiveRecord::Schema.define(:version => 1) do
|
|
39
|
-
create_table :articles do |t|
|
|
40
|
-
t.string :title
|
|
41
|
-
t.string :body
|
|
42
|
-
t.integer :clicks, :default => 0
|
|
43
|
-
t.datetime :created_at, :default => 'NOW()'
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
Article.delete_all
|
|
48
|
-
Article.__elasticsearch__.create_index! force: true
|
|
49
|
-
|
|
50
|
-
::Article.create! title: 'Test', body: '', clicks: 1
|
|
51
|
-
::Article.create! title: 'Testing Coding', body: '', clicks: 2
|
|
52
|
-
::Article.create! title: 'Coding', body: '', clicks: 3
|
|
53
|
-
|
|
54
|
-
Article.__elasticsearch__.refresh_index!
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
should "index and find a document" do
|
|
58
|
-
response = Article.search('title:test')
|
|
59
|
-
|
|
60
|
-
assert response.any?, "Response should not be empty: #{response.to_a.inspect}"
|
|
61
|
-
|
|
62
|
-
assert_equal 2, response.results.size
|
|
63
|
-
assert_equal 2, response.records.size
|
|
64
|
-
|
|
65
|
-
assert_instance_of Elasticsearch::Model::Response::Result, response.results.first
|
|
66
|
-
assert_instance_of Article, response.records.first
|
|
67
|
-
|
|
68
|
-
assert_equal 'Test', response.results.first.title
|
|
69
|
-
assert_equal 'Test', response.records.first.title
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
should "provide access to result" do
|
|
73
|
-
response = Article.search query: { match: { title: 'test' } }, highlight: { fields: { title: {} } }
|
|
74
|
-
|
|
75
|
-
assert_equal 'Test', response.results.first.title
|
|
76
|
-
|
|
77
|
-
assert_equal true, response.results.first.title?
|
|
78
|
-
assert_equal false, response.results.first.boo?
|
|
79
|
-
|
|
80
|
-
assert_equal true, response.results.first.highlight?
|
|
81
|
-
assert_equal true, response.results.first.highlight.title?
|
|
82
|
-
assert_equal false, response.results.first.highlight.boo?
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
should "iterate over results" do
|
|
86
|
-
response = Article.search('title:test')
|
|
87
|
-
|
|
88
|
-
assert_equal ['1', '2'], response.results.map(&:_id)
|
|
89
|
-
assert_equal [1, 2], response.records.map(&:id)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
should "return _id and _type as #id and #type" do
|
|
93
|
-
response = Article.search('title:test')
|
|
94
|
-
|
|
95
|
-
assert_equal '1', response.results.first.id
|
|
96
|
-
assert_equal 'article', response.results.first.type
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
should "access results from records" do
|
|
100
|
-
response = Article.search('title:test')
|
|
101
|
-
|
|
102
|
-
response.records.each_with_hit do |r, h|
|
|
103
|
-
assert_not_nil h._score
|
|
104
|
-
assert_not_nil h._source.title
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
should "preserve the search results order for records" do
|
|
109
|
-
response = Article.search query: { match: { title: 'code' }}, sort: { clicks: :desc }
|
|
110
|
-
|
|
111
|
-
assert_equal response.records[0].clicks, 3
|
|
112
|
-
assert_equal response.records[1].clicks, 2
|
|
113
|
-
|
|
114
|
-
response.records.each_with_hit do |r, h|
|
|
115
|
-
assert_equal h._id, r.id.to_s
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
response.records.map_with_hit do |r, h|
|
|
119
|
-
assert_equal h._id, r.id.to_s
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
should "remove document from index on destroy" do
|
|
124
|
-
article = Article.first
|
|
125
|
-
|
|
126
|
-
article.destroy
|
|
127
|
-
assert_equal 2, Article.count
|
|
128
|
-
|
|
129
|
-
Article.__elasticsearch__.refresh_index!
|
|
130
|
-
|
|
131
|
-
response = Article.search 'title:test'
|
|
132
|
-
|
|
133
|
-
assert_equal 1, response.results.size
|
|
134
|
-
assert_equal 1, response.records.size
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
should "index updates to the document" do
|
|
138
|
-
article = Article.first
|
|
139
|
-
|
|
140
|
-
article.title = 'Writing'
|
|
141
|
-
article.save
|
|
142
|
-
|
|
143
|
-
Article.__elasticsearch__.refresh_index!
|
|
144
|
-
|
|
145
|
-
response = Article.search 'title:write'
|
|
146
|
-
|
|
147
|
-
assert_equal 1, response.results.size
|
|
148
|
-
assert_equal 1, response.records.size
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
should "update specific attributes" do
|
|
152
|
-
article = Article.first
|
|
153
|
-
|
|
154
|
-
response = Article.search 'title:special'
|
|
155
|
-
|
|
156
|
-
assert_equal 0, response.results.size
|
|
157
|
-
assert_equal 0, response.records.size
|
|
158
|
-
|
|
159
|
-
article.__elasticsearch__.update_document_attributes title: 'special'
|
|
160
|
-
|
|
161
|
-
Article.__elasticsearch__.refresh_index!
|
|
162
|
-
|
|
163
|
-
response = Article.search 'title:special'
|
|
164
|
-
|
|
165
|
-
assert_equal 1, response.results.size
|
|
166
|
-
assert_equal 1, response.records.size
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
should "update document when save is called multiple times in a transaction" do
|
|
170
|
-
article = Article.first
|
|
171
|
-
response = Article.search 'body:dummy'
|
|
172
|
-
|
|
173
|
-
assert_equal 0, response.results.size
|
|
174
|
-
assert_equal 0, response.records.size
|
|
175
|
-
|
|
176
|
-
ActiveRecord::Base.transaction do
|
|
177
|
-
article.body = 'dummy'
|
|
178
|
-
article.save
|
|
179
|
-
|
|
180
|
-
article.title = 'special'
|
|
181
|
-
article.save
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
article.__elasticsearch__.update_document
|
|
185
|
-
Article.__elasticsearch__.refresh_index!
|
|
186
|
-
|
|
187
|
-
response = Article.search 'body:dummy'
|
|
188
|
-
assert_equal 1, response.results.size
|
|
189
|
-
assert_equal 1, response.records.size
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
should "return results for a DSL search" do
|
|
193
|
-
response = Article.search query: { match: { title: { query: 'test' } } }
|
|
194
|
-
|
|
195
|
-
assert_equal 2, response.results.size
|
|
196
|
-
assert_equal 2, response.records.size
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
should "return a paged collection" do
|
|
200
|
-
response = Article.search query: { match: { title: { query: 'test' } } },
|
|
201
|
-
size: 2,
|
|
202
|
-
from: 1
|
|
203
|
-
|
|
204
|
-
assert_equal 1, response.results.size
|
|
205
|
-
assert_equal 1, response.records.size
|
|
206
|
-
|
|
207
|
-
assert_equal 'Testing Coding', response.results.first.title
|
|
208
|
-
assert_equal 'Testing Coding', response.records.first.title
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
should "allow chaining SQL commands on response.records" do
|
|
212
|
-
response = Article.search query: { match: { title: { query: 'test' } } }
|
|
213
|
-
|
|
214
|
-
assert_equal 2, response.records.size
|
|
215
|
-
assert_equal 1, response.records.where(title: 'Test').size
|
|
216
|
-
assert_equal 'Test', response.records.where(title: 'Test').first.title
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
should "allow ordering response.records in SQL" do
|
|
220
|
-
response = Article.search query: { match: { title: { query: 'test' } } }
|
|
221
|
-
|
|
222
|
-
if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 4
|
|
223
|
-
assert_equal 'Testing Coding', response.records.order(title: :desc).first.title
|
|
224
|
-
else
|
|
225
|
-
assert_equal 'Testing Coding', response.records.order('title DESC').first.title
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
should "allow dot access to response" do
|
|
230
|
-
response = Article.search query: { match: { title: { query: 'test' } } },
|
|
231
|
-
aggregations: {
|
|
232
|
-
dates: { date_histogram: { field: 'created_at', interval: 'hour' } },
|
|
233
|
-
clicks: { global: {}, aggregations: { min: { min: { field: 'clicks' } } } }
|
|
234
|
-
},
|
|
235
|
-
suggest: { text: 'tezt', title: { term: { field: 'title', suggest_mode: 'always' } } }
|
|
236
|
-
|
|
237
|
-
response.response.respond_to?(:aggregations)
|
|
238
|
-
assert_equal 2, response.aggregations.dates.buckets.first.doc_count
|
|
239
|
-
assert_equal 3, response.aggregations.clicks.doc_count
|
|
240
|
-
assert_equal 1.0, response.aggregations.clicks.min.value
|
|
241
|
-
assert_nil response.aggregations.clicks.max
|
|
242
|
-
|
|
243
|
-
response.response.respond_to?(:suggest)
|
|
244
|
-
assert_equal 1, response.suggestions.title.first.options.size
|
|
245
|
-
assert_equal ['test'], response.suggestions.terms
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
end
|
|
250
|
-
end
|
|
251
|
-
end
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
require 'active_record'
|
|
3
|
-
|
|
4
|
-
# Needed for ActiveRecord 3.x ?
|
|
5
|
-
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ":memory:" ) unless ActiveRecord::Base.connected?
|
|
6
|
-
|
|
7
|
-
::ActiveRecord::Base.raise_in_transactional_callbacks = true if ::ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks) && ::ActiveRecord::VERSION::MAJOR.to_s < '5'
|
|
8
|
-
|
|
9
|
-
module Elasticsearch
|
|
10
|
-
module Model
|
|
11
|
-
class ActiveRecordCustomSerializationTest < Elasticsearch::Test::IntegrationTestCase
|
|
12
|
-
context "ActiveRecord model with custom JSON serialization" do
|
|
13
|
-
setup do
|
|
14
|
-
class ::ArticleWithCustomSerialization < ActiveRecord::Base
|
|
15
|
-
include Elasticsearch::Model
|
|
16
|
-
include Elasticsearch::Model::Callbacks
|
|
17
|
-
|
|
18
|
-
mapping do
|
|
19
|
-
indexes :title
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def as_indexed_json(options={})
|
|
23
|
-
# as_json(options.merge root: false).slice('title')
|
|
24
|
-
{ title: self.title }
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
ActiveRecord::Schema.define(:version => 1) do
|
|
29
|
-
create_table ArticleWithCustomSerialization.table_name do |t|
|
|
30
|
-
t.string :title
|
|
31
|
-
t.string :status
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
ArticleWithCustomSerialization.delete_all
|
|
36
|
-
ArticleWithCustomSerialization.__elasticsearch__.create_index! force: true
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
should "index only the title attribute when creating" do
|
|
40
|
-
ArticleWithCustomSerialization.create! title: 'Test', status: 'green'
|
|
41
|
-
|
|
42
|
-
a = ArticleWithCustomSerialization.__elasticsearch__.client.get \
|
|
43
|
-
index: 'article_with_custom_serializations',
|
|
44
|
-
type: 'article_with_custom_serialization',
|
|
45
|
-
id: '1'
|
|
46
|
-
|
|
47
|
-
assert_equal( { 'title' => 'Test' }, a['_source'] )
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
should "index only the title attribute when updating" do
|
|
51
|
-
ArticleWithCustomSerialization.create! title: 'Test', status: 'green'
|
|
52
|
-
|
|
53
|
-
article = ArticleWithCustomSerialization.first
|
|
54
|
-
article.update_attributes title: 'UPDATED', status: 'red'
|
|
55
|
-
|
|
56
|
-
a = ArticleWithCustomSerialization.__elasticsearch__.client.get \
|
|
57
|
-
index: 'article_with_custom_serializations',
|
|
58
|
-
type: 'article_with_custom_serialization',
|
|
59
|
-
id: '1'
|
|
60
|
-
|
|
61
|
-
assert_equal( { 'title' => 'UPDATED' }, a['_source'] )
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|