elasticsearch_record 1.5.3 → 1.7.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/.yardopts +1 -1
- data/README.md +103 -19
- data/docs/CHANGELOG.md +34 -2
- data/docs/{LICENSE.txt → LICENSE} +1 -1
- data/lib/active_record/connection_adapters/elasticsearch/table_statements.rb +62 -4
- data/lib/active_record/connection_adapters/elasticsearch/transactions.rb +54 -0
- data/lib/active_record/connection_adapters/elasticsearch/unsupported_implementation.rb +0 -7
- data/lib/active_record/connection_adapters/elasticsearch_adapter.rb +17 -3
- data/lib/arel/collectors/elasticsearch_query.rb +3 -0
- data/lib/elasticsearch_record/core.rb +15 -2
- data/lib/elasticsearch_record/gem_version.rb +2 -2
- data/lib/elasticsearch_record/instrumentation/log_subscriber.rb +7 -3
- data/lib/elasticsearch_record/model_api.rb +68 -10
- data/lib/elasticsearch_record/model_schema.rb +2 -5
- data/lib/elasticsearch_record/persistence.rb +13 -1
- data/lib/elasticsearch_record/query.rb +19 -7
- data/lib/elasticsearch_record/querying.rb +36 -1
- data/lib/elasticsearch_record/relation/calculation_methods.rb +120 -5
- data/lib/elasticsearch_record/relation/core_methods.rb +12 -0
- data/lib/elasticsearch_record/relation/query_methods.rb +10 -0
- data/lib/elasticsearch_record/relation/result_methods.rb +42 -5
- data/lib/elasticsearch_record/result.rb +1 -1
- data/lib/elasticsearch_record.rb +10 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92676fe7f2327036588c1d2e3cb6756cabbc2365ee8984196f1ef1c4a23d8448
|
4
|
+
data.tar.gz: 8c1f329957f4a1909181dde9e9c781a86a41188ee7337a73614eb8d893cae482
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cb4514641f1f26d922f5cb941a677c5cff568641ddcf7243a914481707a982440b6a8967e74734d7900c00c6441128ef69c29a5c3774455df018206932e1b85
|
7
|
+
data.tar.gz: 004b62c74a4b4878c2e0a982a91217beee695a8e58d4509bba4cbd8f7664fdd0a4658cfd8533e1ff5a409f5fee6bce613d46f398ac067ed474324d65ad43406c
|
data/.yardopts
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[](http://rubydoc.info/gems/elasticsearch_record)
|
5
5
|
|
6
6
|
[](https://badge.fury.io/rb/elasticsearch_record)
|
7
|
-
[](docs/LICENSE
|
7
|
+
[](docs/LICENSE)
|
8
8
|
|
9
9
|
ActiveRecord adapter for Elasticsearch
|
10
10
|
|
@@ -14,8 +14,28 @@ _ElasticsearchRecord is a ActiveRecord adapter and provides similar functionalit
|
|
14
14
|
|
15
15
|
**PLEASE NOTE:**
|
16
16
|
|
17
|
-
-
|
18
|
-
-
|
17
|
+
- This is the `rails-7-0-stable`-branch, which only supports rails **7.0** _(see section 'Rails_Versions' for supported versions)_
|
18
|
+
- supports ActiveRecord ~> 7.0 + Elasticsearch >= 7.17
|
19
|
+
|
20
|
+
-----
|
21
|
+
|
22
|
+
## Rails versions
|
23
|
+
|
24
|
+
Supported rails versions:
|
25
|
+
|
26
|
+
### Rails 7.1:
|
27
|
+
_(since gem version 1.8)_
|
28
|
+
|
29
|
+
https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-1-stable
|
30
|
+
|
31
|
+
[](https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-1-stable)
|
32
|
+
|
33
|
+
### Rails 7.0:
|
34
|
+
_(until gem version 1.7)_
|
35
|
+
|
36
|
+
https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-0-stable
|
37
|
+
|
38
|
+
[](https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-0-stable)
|
19
39
|
|
20
40
|
-----
|
21
41
|
|
@@ -24,7 +44,11 @@ _ElasticsearchRecord is a ActiveRecord adapter and provides similar functionalit
|
|
24
44
|
Add this line to your application's Gemfile:
|
25
45
|
|
26
46
|
```ruby
|
27
|
-
gem 'elasticsearch_record'
|
47
|
+
gem 'elasticsearch_record', '~> 1.7'
|
48
|
+
|
49
|
+
# alternative
|
50
|
+
gem 'elasticsearch_record', git: 'https://github.com/ruby-smart/elasticsearch_record', branch: 'rails-7-0-stable'
|
51
|
+
|
28
52
|
```
|
29
53
|
|
30
54
|
And then execute:
|
@@ -53,6 +77,22 @@ Or install it yourself as:
|
|
53
77
|
* logs Elasticsearch API-calls
|
54
78
|
* shows Runtime in logs
|
55
79
|
|
80
|
+
## Notice
|
81
|
+
Since ActiveRecord does not have any configuration option to support transactions and
|
82
|
+
Elasticsearch does **NOT** support transactions, it may be risky to ignore them.
|
83
|
+
|
84
|
+
As a default, transactions are 'silently swallowed' to not break any existing applications...
|
85
|
+
|
86
|
+
To raise an exception while using transactions on a ElasticsearchRecord model, the following flag can be enabled.
|
87
|
+
However enabling this flag will surely fail transactional tests _(prevent this with 'use_transactional_tests=false')_
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
# config/initializers/elasticsearch_record.yml
|
91
|
+
|
92
|
+
# enable transactional exceptions
|
93
|
+
ElasticsearchRecord.error_on_transaction = true
|
94
|
+
```
|
95
|
+
|
56
96
|
## Setup
|
57
97
|
|
58
98
|
### a) Update your **database.yml** and add a elasticsearch connection:
|
@@ -219,11 +259,25 @@ total = scope.total
|
|
219
259
|
# > 3335
|
220
260
|
```
|
221
261
|
|
262
|
+
### Available core query methods
|
263
|
+
|
264
|
+
- find_by_sql
|
265
|
+
- find_by_query
|
266
|
+
- find_by_esql
|
267
|
+
- esql
|
268
|
+
- msearch
|
269
|
+
- search
|
270
|
+
|
271
|
+
_see simple documentation about these methods @ {ElasticsearchRecord::Querying rubydoc}_
|
272
|
+
|
273
|
+
_(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/querying.rb) )_
|
274
|
+
|
222
275
|
### Available query/relation chain methods
|
223
276
|
- kind
|
224
277
|
- configure
|
225
278
|
- aggregate
|
226
279
|
- refresh
|
280
|
+
- timeout
|
227
281
|
- query
|
228
282
|
- filter
|
229
283
|
- must_not
|
@@ -235,7 +289,9 @@ total = scope.total
|
|
235
289
|
- aggs_only!
|
236
290
|
- total_only!
|
237
291
|
|
238
|
-
_see simple documentation about these methods @
|
292
|
+
_see simple documentation about these methods @ {ElasticsearchRecord::Relation::QueryMethods rubydoc}_
|
293
|
+
|
294
|
+
_(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/relation/query_methods.rb) )_
|
239
295
|
|
240
296
|
### Available calculation methods
|
241
297
|
- percentiles
|
@@ -245,9 +301,16 @@ _see simple documentation about these methods @ [rubydoc](https://rubydoc.info/g
|
|
245
301
|
- minimum
|
246
302
|
- maximum
|
247
303
|
- sum
|
304
|
+
- boxplot
|
305
|
+
- stats
|
306
|
+
- string_stats
|
307
|
+
- matrix_stats
|
308
|
+
- median_absolute_deviation
|
248
309
|
- calculate
|
249
310
|
|
250
|
-
_see simple documentation about these methods @
|
311
|
+
_see simple documentation about these methods @ {ElasticsearchRecord::Relation::CalculationMethods rubydoc}_
|
312
|
+
|
313
|
+
_(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/relation/calculation_methods.rb) )_
|
251
314
|
|
252
315
|
### Available result methods
|
253
316
|
- aggregations
|
@@ -260,8 +323,11 @@ _see simple documentation about these methods @ [rubydoc](https://rubydoc.info/g
|
|
260
323
|
- composite
|
261
324
|
- point_in_time
|
262
325
|
- pit_results
|
326
|
+
- pit_delete
|
263
327
|
|
264
|
-
_see simple documentation about these methods @
|
328
|
+
_see simple documentation about these methods @ {ElasticsearchRecord::Relation::ResultMethods rubydoc}_
|
329
|
+
|
330
|
+
_(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/relation/result_methods.rb) )_
|
265
331
|
|
266
332
|
### Additional methods
|
267
333
|
- to_query
|
@@ -366,13 +432,26 @@ SearchUser.api.mappings
|
|
366
432
|
SearchUser.api.insert([{name: 'Hans', age: 34}, {name: 'Peter', age: 22}])
|
367
433
|
```
|
368
434
|
|
435
|
+
### dangerous methods
|
369
436
|
* open!
|
370
437
|
* close!
|
371
438
|
* refresh!
|
372
439
|
* block!
|
373
440
|
* unblock!
|
441
|
+
|
442
|
+
### dangerous methods with args
|
443
|
+
* create!(...)
|
444
|
+
* clone!(...)
|
445
|
+
* rename!(...)
|
446
|
+
* backup!(...)
|
447
|
+
* restore!(...)
|
448
|
+
* reindex!(...)
|
449
|
+
|
450
|
+
### dangerous methods with confirm parameter
|
374
451
|
* drop!(confirm: true)
|
375
452
|
* truncate!(confirm: true)
|
453
|
+
|
454
|
+
### table methods
|
376
455
|
* mappings
|
377
456
|
* metas
|
378
457
|
* settings
|
@@ -380,17 +459,19 @@ SearchUser.api.insert([{name: 'Hans', age: 34}, {name: 'Peter', age: 22}])
|
|
380
459
|
* state
|
381
460
|
* schema
|
382
461
|
* exists?
|
383
|
-
|
384
|
-
|
385
|
-
*
|
386
|
-
*
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
*
|
392
|
-
*
|
393
|
-
*
|
462
|
+
|
463
|
+
### plain methods
|
464
|
+
* alias_exists?(...)
|
465
|
+
* setting_exists?(...)
|
466
|
+
* mapping_exists?(...)
|
467
|
+
* meta_exists?(...)
|
468
|
+
|
469
|
+
### Fast insert, update, delete raw data
|
470
|
+
* index(...)
|
471
|
+
* insert(...)
|
472
|
+
* update(...)
|
473
|
+
* delete(...)
|
474
|
+
* bulk(...)
|
394
475
|
|
395
476
|
-----
|
396
477
|
|
@@ -436,6 +517,9 @@ Access these methods through the model's connection or within any `Migration`.
|
|
436
517
|
- create_table
|
437
518
|
- change_table
|
438
519
|
- rename_table
|
520
|
+
- reindex_table
|
521
|
+
- backup_table
|
522
|
+
- restore_table
|
439
523
|
|
440
524
|
### table actions:
|
441
525
|
- change_meta
|
@@ -584,7 +668,7 @@ This project is intended to be a safe, welcoming space for collaboration, and co
|
|
584
668
|
|
585
669
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
586
670
|
|
587
|
-
A copy of the [LICENSE](docs/LICENSE
|
671
|
+
A copy of the [LICENSE](docs/LICENSE) can be found @ the docs.
|
588
672
|
|
589
673
|
## Code of Conduct
|
590
674
|
|
data/docs/CHANGELOG.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
# ElasticsearchRecord - CHANGELOG
|
2
2
|
|
3
|
+
## [1.7.0] - 2024-01-09
|
4
|
+
* [add] `ElasticsearchRecord::Relation#boxplot` calculation method
|
5
|
+
* [add] `ElasticsearchRecord::Relation#stats` calculation method
|
6
|
+
* [add] `ElasticsearchRecord::Relation#string_stats` calculation method
|
7
|
+
* [add] `ElasticsearchRecord::Relation#matrix_stats` calculation method
|
8
|
+
* [add] `ElasticsearchRecord::Relation#median_absolute_deviation` calculation method
|
9
|
+
* [add] `ElasticsearchRecord::Base#esql` + `ElasticsearchRecord::Base#find_by_esql` to support `ES|QL` queries
|
10
|
+
* [add] new repository branch `rails-7-0-stable` to support different rails versions
|
11
|
+
* [ref] minor code optimizations & documentation changes
|
12
|
+
|
13
|
+
## [1.6.0] - 2023-08-11
|
14
|
+
* [add] `ElasticsearchRecord::Base#undelegate_id_attribute_with` method to support a temporary 'undelegation' (used to create a new record)
|
15
|
+
* [add] `ElasticsearchRecord::Relation#timeout` to directly provide the timeout-parameter to the query
|
16
|
+
* [add] `ElasticsearchRecord.error_on_transaction`-flag to throw transactional errors (default: `false`) - this will now **IGNORE** all transactions
|
17
|
+
* [add] `ElasticsearchRecord::ModelApi` create!, clone!, rename!, backup!, restore! & reindex!-methods
|
18
|
+
* [add] `ElasticsearchRecord::Relation#pit_delete` which executes a delete query in a 'point_in_time' scope.
|
19
|
+
* [add] `ActiveRecord::ConnectionAdapters::Elasticsearch::TableStatements#backup_table` to create a backup (snapshot) of the entire table (index)
|
20
|
+
* [add] `ActiveRecord::ConnectionAdapters::Elasticsearch::TableStatements#restore_table` to restore a entire table (index)
|
21
|
+
* [add] `ActiveRecord::ConnectionAdapters::Elasticsearch::TableStatements#reindex_table` to copy documents from source to destination
|
22
|
+
* [ref] `ElasticsearchRecord::Base.delegate_id_attribute` now supports instance writer
|
23
|
+
* [ref] `ElasticsearchRecord::Relation#pit_results` adds `ids_only`-parameter to now support a simple return of the records-ids...
|
24
|
+
* [fix] Relation `#last`-method will raise an transport exception if cluster setting '**indices.id_field_data.enabled**' is disabled (now checks for `access_id_fielddata?`)
|
25
|
+
* [fix] ElasticsearchRecord-connection settings does not support `username` key
|
26
|
+
* [fix] ElasticsearchRecord-connection settings does not support `port` key
|
27
|
+
* [fix] `_id`-Attribute is erroneously defined as 'virtual' attribute - but is required for insert statements.
|
28
|
+
* [fix] unsupported **SAVEPOINT** transactions throws exceptions _(especially in tests)_
|
29
|
+
* [fix] `ElasticsearchRecord::ModelApi#bulk` does not recognize `'_id' / :_id` attribute
|
30
|
+
* [fix] `ElasticsearchRecord::ModelApi#bulk` does not correctly build the data-hash for `update`-operation _(missing 'doc'-node)_
|
31
|
+
* [ref] simplify `ElasticsearchRecord::Base#searchable_column_names`
|
32
|
+
* [fix] creating a new record does not recognize a manually provided `_id`-attribute
|
33
|
+
* [fix] creating a new record with active `delegate_id_attribute`-flag does not update the records `_id`.
|
34
|
+
|
3
35
|
## [1.5.3] - 2023-07-14
|
4
36
|
* [fix] `ElasticsearchRecord::Relation#where!` on nested, provided `:none` key
|
5
37
|
* [ref] minor code tweaks and comment updates
|
@@ -13,10 +45,10 @@
|
|
13
45
|
|
14
46
|
## [1.5.0] - 2023-07-10
|
15
47
|
* [add] additional `ElasticsearchRecord::ModelApi` methods **drop!** & **truncate!**, which have to be called with a `confirm:true` parameter
|
16
|
-
* [add]
|
48
|
+
* [add] `ElasticsearchRecord::Base.delegate_query_nil_limit` to automatically delegate a relations `limit(nil)`-call to the **max_result_window** _(set to 10.000 as default)_
|
17
49
|
* [add] `ActiveRecord::ConnectionAdapters::Elasticsearch::SchemaStatements#access_shard_doc?` which checks, if the **PIT**-shard_doc order is available
|
18
50
|
* [add] support for **_shard_doc** as a default order for `ElasticsearchRecord::Relation#pit_results`
|
19
|
-
* [ref]
|
51
|
+
* [ref] `ElasticsearchRecord::Base.relay_id_attribute` to a more coherent name: `delegate_id_attribute`
|
20
52
|
* [ref] `ElasticsearchRecord::Relation#ordered_relation` to optimize already ordered relations
|
21
53
|
* [ref] gemspecs to support different versions of Elasticsearch
|
22
54
|
* [ref] improved README
|
@@ -116,7 +116,7 @@ module ActiveRecord
|
|
116
116
|
# Defaults to false.
|
117
117
|
# @param [String] table_name
|
118
118
|
# @param [Boolean] if_exists
|
119
|
-
# @return [
|
119
|
+
# @return [Boolean] acknowledged status
|
120
120
|
def drop_table(table_name, if_exists: false, **)
|
121
121
|
schema_cache.clear_data_source_cache!(table_name)
|
122
122
|
api(:indices, :delete, { index: table_name, ignore: (if_exists ? 404 : nil) }, 'DROP TABLE').dig('acknowledged')
|
@@ -148,11 +148,12 @@ module ActiveRecord
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
151
|
-
# clones an entire table (index) to the provided +target_name+.
|
151
|
+
# clones an entire table (index) with its docs to the provided +target_name+.
|
152
152
|
# During cloning, the table will be automatically 'write'-blocked.
|
153
153
|
# @param [String] table_name
|
154
154
|
# @param [String] target_name
|
155
155
|
# @param [Hash] options
|
156
|
+
# @return [Boolean] acknowledged status
|
156
157
|
def clone_table(table_name, target_name, **options)
|
157
158
|
# create new definition
|
158
159
|
definition = clone_table_definition(table_name, target_name, **extract_table_options!(options))
|
@@ -168,6 +169,54 @@ module ActiveRecord
|
|
168
169
|
definition.exec!
|
169
170
|
end
|
170
171
|
|
172
|
+
# creates a backup (snapshot) of the entire table (index) from provided +table_name+.
|
173
|
+
# The backup will be closed, to prevent read/write access.
|
174
|
+
# The +target_name+ will be auto-generated, if not provided.
|
175
|
+
#
|
176
|
+
# @example
|
177
|
+
# backup_table('screenshots', to: 'screenshots-backup-v1')
|
178
|
+
#
|
179
|
+
# @param [String] table_name
|
180
|
+
# @param [String] to - target_name
|
181
|
+
# @param [Boolean] close - closes backup after creation (default: true)
|
182
|
+
# @return [String] backup_name
|
183
|
+
def backup_table(table_name, to: nil, close: true)
|
184
|
+
to ||= "#{table_name}-snapshot-#{Time.now.strftime('%s%3N')}"
|
185
|
+
raise ArgumentError, "unable to backup '#{table_name}' to already existing target '#{to}'!" if table_exists?(to)
|
186
|
+
|
187
|
+
clone_table(table_name, to)
|
188
|
+
close_table(to) if close
|
189
|
+
|
190
|
+
to
|
191
|
+
end
|
192
|
+
|
193
|
+
# restores a entire table (index) from provided +target_name+.
|
194
|
+
# The +table_name+ will be dropped, if exists.
|
195
|
+
# The +from+ will persist, if not provided +drop_backup:true+.
|
196
|
+
#
|
197
|
+
# @example
|
198
|
+
# restore_table('screenshots', from: 'screenshots-backup-v1')
|
199
|
+
#
|
200
|
+
# @param [String] table_name
|
201
|
+
# @param [String] from
|
202
|
+
# @param [String (frozen)] timeout - renaming timout (default: '30s')
|
203
|
+
# @param [Boolean] open - opens restored backup after creation (default: true)
|
204
|
+
# @return [Boolean] acknowledged status
|
205
|
+
def restore_table(table_name, from:, timeout: nil, open: true, drop_backup: false)
|
206
|
+
raise ArgumentError, "unable to restore from missing target '#{from}'!" unless table_exists?(from)
|
207
|
+
drop_table(table_name, if_exists: true)
|
208
|
+
|
209
|
+
# choose best strategy
|
210
|
+
if drop_backup
|
211
|
+
rename_table(from, table_name, timeout: timeout)
|
212
|
+
else
|
213
|
+
clone_table(from, table_name)
|
214
|
+
end
|
215
|
+
|
216
|
+
# open, if provided
|
217
|
+
open_table(from) if open
|
218
|
+
end
|
219
|
+
|
171
220
|
# renames a table (index) by executing multiple steps:
|
172
221
|
# - clone table
|
173
222
|
# - wait for 'green' state
|
@@ -178,11 +227,11 @@ module ActiveRecord
|
|
178
227
|
# @param [String] target_name
|
179
228
|
# @param [String (frozen)] timeout (default: '30s')
|
180
229
|
# @param [Hash] options - additional 'clone' options (like settings, alias, ...)
|
181
|
-
def rename_table(table_name, target_name, timeout:
|
230
|
+
def rename_table(table_name, target_name, timeout: nil, **options)
|
182
231
|
schema_cache.clear_data_source_cache!(table_name)
|
183
232
|
|
184
233
|
clone_table(table_name, target_name, **options)
|
185
|
-
cluster_health(index: target_name, wait_for_status: 'green', timeout: timeout)
|
234
|
+
cluster_health(index: target_name, wait_for_status: 'green', timeout: timeout.presence || '30s')
|
186
235
|
drop_table(table_name)
|
187
236
|
end
|
188
237
|
|
@@ -255,6 +304,15 @@ module ActiveRecord
|
|
255
304
|
definition.exec!
|
256
305
|
end
|
257
306
|
|
307
|
+
# Copies documents from a source to a destination.
|
308
|
+
# @param [String] table_name
|
309
|
+
# @param [String] target_name
|
310
|
+
# @param [Hash] options
|
311
|
+
# @return [Hash] reindex stats
|
312
|
+
def reindex_table(table_name, target_name, **options)
|
313
|
+
api(:core, :reindex, { body: { source: { index: table_name }, dest: { index: target_name } } }.merge(options), 'REINDEX TABLE')
|
314
|
+
end
|
315
|
+
|
258
316
|
# -- mapping -------------------------------------------------------------------------------------------------
|
259
317
|
|
260
318
|
def add_mapping(table_name, name, type, **options, &block)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Elasticsearch
|
6
|
+
module Transactions
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
def transaction(*)
|
10
|
+
# since ActiveRecord does not have any configuration option to support transactions,
|
11
|
+
# this will be always false
|
12
|
+
# return super if supports_transactions?
|
13
|
+
#
|
14
|
+
# So, transactions are silently swallowed...
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
|
18
|
+
# Begins the transaction (and turns off auto-committing).
|
19
|
+
def begin_db_transaction(*)
|
20
|
+
_throw_transaction_exception!(:begin_db_transaction)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Commits the transaction (and turns on auto-committing).
|
24
|
+
def commit_db_transaction(*)
|
25
|
+
_throw_transaction_exception!(:commit_db_transaction)
|
26
|
+
end
|
27
|
+
|
28
|
+
# rollback transaction
|
29
|
+
def exec_rollback_db_transaction(*)
|
30
|
+
_throw_transaction_exception!(:exec_rollback_db_transaction)
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_savepoint(*)
|
34
|
+
_throw_transaction_exception!(:create_savepoint)
|
35
|
+
end
|
36
|
+
|
37
|
+
def exec_rollback_to_savepoint(*)
|
38
|
+
_throw_transaction_exception!(:exec_rollback_to_savepoint)
|
39
|
+
end
|
40
|
+
|
41
|
+
def release_savepoint(*)
|
42
|
+
_throw_transaction_exception!(:release_savepoint)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def _throw_transaction_exception!(method_name)
|
48
|
+
return unless ElasticsearchRecord.error_on_transaction
|
49
|
+
raise NotImplementedError, "'##{method_name}' is not supported by Elasticsearch.\nTry to prevent transactions or set the 'ElasticsearchRecord.error_on_transaction' to false!"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -3,13 +3,6 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
5
|
module Elasticsearch
|
6
|
-
|
7
|
-
class UnsupportedImplementationError < StandardError
|
8
|
-
def initialize(method_name)
|
9
|
-
super "Unsupported implementation of method: #{method_name}."
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
6
|
module UnsupportedImplementation
|
14
7
|
extend ActiveSupport::Concern
|
15
8
|
|
@@ -13,6 +13,7 @@ require 'active_record/connection_adapters/elasticsearch/schema_dumper'
|
|
13
13
|
require 'active_record/connection_adapters/elasticsearch/schema_statements'
|
14
14
|
require 'active_record/connection_adapters/elasticsearch/type'
|
15
15
|
require 'active_record/connection_adapters/elasticsearch/table_statements'
|
16
|
+
require 'active_record/connection_adapters/elasticsearch/transactions'
|
16
17
|
|
17
18
|
require 'arel/visitors/elasticsearch'
|
18
19
|
require 'arel/collectors/elasticsearch_query'
|
@@ -25,6 +26,12 @@ module ActiveRecord # :nodoc:
|
|
25
26
|
def elasticsearch_connection(config)
|
26
27
|
config = config.symbolize_keys
|
27
28
|
|
29
|
+
# move 'username' to 'user'
|
30
|
+
config[:user] = config.delete(:username) if config[:username]
|
31
|
+
|
32
|
+
# append 'port' to 'host'
|
33
|
+
config[:host] += ":#{config.delete(:port)}" if config[:port] && config[:host]
|
34
|
+
|
28
35
|
# move 'host' to 'hosts'
|
29
36
|
config[:hosts] = config.delete(:host) if config[:host]
|
30
37
|
|
@@ -45,7 +52,7 @@ module ActiveRecord # :nodoc:
|
|
45
52
|
|
46
53
|
# defines the Elasticsearch 'base' structure, which is always included but cannot be resolved through mappings ...
|
47
54
|
BASE_STRUCTURE = [
|
48
|
-
{ 'name' => '_id', 'type' => 'keyword', '
|
55
|
+
{ 'name' => '_id', 'type' => 'keyword', 'meta' => { 'primary_key' => 'true' } },
|
49
56
|
{ 'name' => '_index', 'type' => 'keyword', 'virtual' => true },
|
50
57
|
{ 'name' => '_score', 'type' => 'float', 'virtual' => true },
|
51
58
|
{ 'name' => '_type', 'type' => 'keyword', 'virtual' => true },
|
@@ -57,6 +64,7 @@ module ActiveRecord # :nodoc:
|
|
57
64
|
include Elasticsearch::DatabaseStatements
|
58
65
|
include Elasticsearch::SchemaStatements
|
59
66
|
include Elasticsearch::TableStatements
|
67
|
+
include Elasticsearch::Transactions
|
60
68
|
|
61
69
|
class << self
|
62
70
|
def base_structure_keys
|
@@ -69,7 +77,7 @@ module ActiveRecord # :nodoc:
|
|
69
77
|
client.ping unless config[:ping] == false
|
70
78
|
client
|
71
79
|
rescue ::Elastic::Transport::Transport::Errors::Unauthorized
|
72
|
-
raise ActiveRecord::DatabaseConnectionError.username_error(config[:
|
80
|
+
raise ActiveRecord::DatabaseConnectionError.username_error(config[:user])
|
73
81
|
rescue ::Elastic::Transport::Transport::ServerError => error
|
74
82
|
raise ::ActiveRecord::ConnectionNotEstablished, error.message
|
75
83
|
end
|
@@ -135,7 +143,7 @@ module ActiveRecord # :nodoc:
|
|
135
143
|
|
136
144
|
# define native types - which will be used for schema-dumping
|
137
145
|
NATIVE_DATABASE_TYPES = {
|
138
|
-
primary_key: { name: 'long' },
|
146
|
+
primary_key: { name: 'long' }, # maybe this hae to changed to 'keyword'
|
139
147
|
string: { name: 'keyword' },
|
140
148
|
blob: { name: 'binary' },
|
141
149
|
datetime: { name: 'date' },
|
@@ -172,6 +180,12 @@ module ActiveRecord # :nodoc:
|
|
172
180
|
@config[:migrations_paths] || ['db/migrate_elasticsearch']
|
173
181
|
end
|
174
182
|
|
183
|
+
# Does this adapter support transactions in general?
|
184
|
+
# HINT: This is +NOT* an official setting and only introduced to ElasticsearchRecord
|
185
|
+
def supports_transactions?
|
186
|
+
false
|
187
|
+
end
|
188
|
+
|
175
189
|
# Does this adapter support explain?
|
176
190
|
def supports_explain?
|
177
191
|
false
|
@@ -8,7 +8,7 @@ module ElasticsearchRecord
|
|
8
8
|
# this through +_read_attribute(:id)+.
|
9
9
|
# To also have the ability of accessing this attribute through the default, this flag can be enabled.
|
10
10
|
# @attribute! Boolean
|
11
|
-
class_attribute :delegate_id_attribute,
|
11
|
+
class_attribute :delegate_id_attribute, default: false
|
12
12
|
|
13
13
|
# Elasticsearch's default value for queries without a +size+ is forced to +10+.
|
14
14
|
# To provide a similar behaviour as SQL, this can be automatically set to the +max_result_window+ value.
|
@@ -45,7 +45,7 @@ module ElasticsearchRecord
|
|
45
45
|
|
46
46
|
# overwrite to provide a Elasticsearch version of returning a 'primary_key' was attribute.
|
47
47
|
# Elasticsearch uses the static +_id+ column as primary_key, but also supports an additional +id+ column.
|
48
|
-
# To provide functionality of returning the +
|
48
|
+
# To provide functionality of returning the +id_was+ attribute, this method must also support it
|
49
49
|
# with enabled +delegate_id_attribute+.
|
50
50
|
def id_was
|
51
51
|
delegate_id_attribute? && has_attribute?('id') ? attribute_was('id') : super
|
@@ -69,6 +69,19 @@ module ElasticsearchRecord
|
|
69
69
|
super
|
70
70
|
end
|
71
71
|
|
72
|
+
# resets a possible active +delegate_id_attribute?+ to false during block execution.
|
73
|
+
# Unfortunately this is required, since a lot of rails-code forces 'accessors' on the primary_key-field through the
|
74
|
+
# +id+-getter & setter methods. This will then fail to set the doc-_id and instead set the +id+-attribute ...
|
75
|
+
def undelegate_id_attribute_with(&block)
|
76
|
+
return block.call unless self.delegate_id_attribute?
|
77
|
+
|
78
|
+
self.delegate_id_attribute = false
|
79
|
+
result = block.call
|
80
|
+
self.delegate_id_attribute = true
|
81
|
+
|
82
|
+
result
|
83
|
+
end
|
84
|
+
|
72
85
|
module PrependClassMethods
|
73
86
|
# returns the table_name.
|
74
87
|
# Has to be prepended to provide automated compatibility to other gems.
|
@@ -46,7 +46,7 @@ module ElasticsearchRecord
|
|
46
46
|
|
47
47
|
# final coloring
|
48
48
|
name = color(name, name_color(payload[:name]), true)
|
49
|
-
query = color(query, gate_color(payload[:gate]), true) if colorize_logging
|
49
|
+
query = color(query, gate_color(payload[:gate], payload[:name]), true) if colorize_logging
|
50
50
|
|
51
51
|
debug " #{name} #{query.presence || '-/-'}"
|
52
52
|
end
|
@@ -61,7 +61,7 @@ module ElasticsearchRecord
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
def gate_color(gate)
|
64
|
+
def gate_color(gate, name)
|
65
65
|
case gate
|
66
66
|
# SELECTS
|
67
67
|
when 'core.get', 'core.mget', 'core.search', 'core.msearch', 'core.count', 'core.exists', 'sql.query'
|
@@ -77,7 +77,11 @@ module ElasticsearchRecord
|
|
77
77
|
YELLOW
|
78
78
|
# MIXINS
|
79
79
|
when /indices\.\w+/, 'core.bulk', 'core.index'
|
80
|
-
|
80
|
+
if name.end_with?('Pit Delete')
|
81
|
+
RED
|
82
|
+
else
|
83
|
+
WHITE
|
84
|
+
end
|
81
85
|
else
|
82
86
|
MAGENTA
|
83
87
|
end
|