elasticsearch_record 1.0.2 → 1.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/.yardopts +4 -0
- data/Gemfile.lock +10 -14
- data/README.md +180 -27
- data/docs/CHANGELOG.md +36 -18
- data/docs/LICENSE.txt +1 -1
- data/elasticsearch_record.gemspec +42 -0
- data/lib/active_record/connection_adapters/elasticsearch/column.rb +20 -6
- data/lib/active_record/connection_adapters/elasticsearch/database_statements.rb +142 -125
- data/lib/active_record/connection_adapters/elasticsearch/quoting.rb +2 -23
- data/lib/active_record/connection_adapters/elasticsearch/schema_creation.rb +30 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/attribute_methods.rb +103 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/column_methods.rb +42 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/create_table_definition.rb +158 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_alias_definition.rb +32 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb +132 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_mapping_definition.rb +110 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_setting_definition.rb +136 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/update_table_definition.rb +174 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_definitions.rb +37 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_dumper.rb +110 -0
- data/lib/active_record/connection_adapters/elasticsearch/schema_statements.rb +398 -174
- data/lib/active_record/connection_adapters/elasticsearch/table_statements.rb +232 -0
- data/lib/active_record/connection_adapters/elasticsearch/type/multicast_value.rb +2 -0
- data/lib/active_record/connection_adapters/elasticsearch/unsupported_implementation.rb +32 -0
- data/lib/active_record/connection_adapters/elasticsearch_adapter.rb +112 -19
- data/lib/arel/collectors/elasticsearch_query.rb +0 -1
- data/lib/arel/visitors/elasticsearch.rb +7 -579
- data/lib/arel/visitors/elasticsearch_base.rb +234 -0
- data/lib/arel/visitors/elasticsearch_query.rb +463 -0
- data/lib/arel/visitors/elasticsearch_schema.rb +124 -0
- data/lib/elasticsearch_record/core.rb +44 -10
- data/lib/elasticsearch_record/errors.rb +13 -0
- data/lib/elasticsearch_record/gem_version.rb +6 -2
- data/lib/elasticsearch_record/instrumentation/log_subscriber.rb +27 -9
- data/lib/elasticsearch_record/model_schema.rb +5 -0
- data/lib/elasticsearch_record/persistence.rb +31 -26
- data/lib/elasticsearch_record/query.rb +56 -17
- data/lib/elasticsearch_record/querying.rb +17 -0
- data/lib/elasticsearch_record/relation/calculation_methods.rb +3 -0
- data/lib/elasticsearch_record/relation/core_methods.rb +57 -17
- data/lib/elasticsearch_record/relation/query_clause_tree.rb +38 -1
- data/lib/elasticsearch_record/relation/query_methods.rb +6 -0
- data/lib/elasticsearch_record/relation/result_methods.rb +15 -9
- data/lib/elasticsearch_record/result.rb +32 -5
- data/lib/elasticsearch_record/statement_cache.rb +2 -1
- data/lib/elasticsearch_record.rb +2 -2
- metadata +29 -11
- data/.ruby-version +0 -1
- data/lib/elasticsearch_record/schema_migration.rb +0 -30
@@ -3,7 +3,7 @@
|
|
3
3
|
module ElasticsearchRecord # :nodoc:
|
4
4
|
module Relation
|
5
5
|
class QueryClauseTree
|
6
|
-
delegate :any?, :empty?, :key?, :each, to: :predicates
|
6
|
+
delegate :any?, :empty?, :key?, :keys, :each, to: :predicates
|
7
7
|
|
8
8
|
def self.empty
|
9
9
|
@empty ||= new({}).freeze
|
@@ -39,6 +39,12 @@ module ElasticsearchRecord # :nodoc:
|
|
39
39
|
QueryClauseTree.new(dups)
|
40
40
|
end
|
41
41
|
|
42
|
+
def [](key)
|
43
|
+
return nil unless key?(key)
|
44
|
+
|
45
|
+
dupredicates[key]
|
46
|
+
end
|
47
|
+
|
42
48
|
def +(other)
|
43
49
|
dups = dupredicates
|
44
50
|
|
@@ -52,6 +58,17 @@ module ElasticsearchRecord # :nodoc:
|
|
52
58
|
end
|
53
59
|
|
54
60
|
def -(other)
|
61
|
+
# check for provided :tree
|
62
|
+
if other.key == :tree
|
63
|
+
scope = self
|
64
|
+
|
65
|
+
(scope.keys & other.keys).each do |key|
|
66
|
+
scope -= other[key]
|
67
|
+
end
|
68
|
+
|
69
|
+
return scope
|
70
|
+
end
|
71
|
+
|
55
72
|
dups = dupredicates
|
56
73
|
|
57
74
|
if key?(other.key)
|
@@ -79,6 +96,26 @@ module ElasticsearchRecord # :nodoc:
|
|
79
96
|
predicates == other.predicates
|
80
97
|
end
|
81
98
|
|
99
|
+
def or(other)
|
100
|
+
left = self - other
|
101
|
+
common = self - left
|
102
|
+
right = other - common
|
103
|
+
|
104
|
+
if left.empty? || right.empty?
|
105
|
+
common
|
106
|
+
else
|
107
|
+
key = other.keys[0]
|
108
|
+
|
109
|
+
left = left[key]
|
110
|
+
right = right[key]
|
111
|
+
|
112
|
+
or_clause = Arel::Nodes::Or.new(left, right)
|
113
|
+
|
114
|
+
common.predicates[key] = ElasticsearchRecord::Relation::QueryClause.new(key, [Arel::Nodes::Grouping.new(or_clause)])
|
115
|
+
common
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
82
119
|
protected
|
83
120
|
|
84
121
|
attr_reader :predicates
|
@@ -4,11 +4,11 @@ module ElasticsearchRecord
|
|
4
4
|
# aggregate pluck provided columns.
|
5
5
|
# returns a hash of values for each provided column
|
6
6
|
#
|
7
|
-
#
|
8
|
-
#
|
7
|
+
# Person.agg_pluck(:name)
|
8
|
+
# #> {"name" => ['David', 'Jeremy', 'Jose']}
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
10
|
+
# Person.agg_pluck(:id, :name)
|
11
|
+
# #> {"id" => ['11', '2', '5'], "name" => ['David', 'Jeremy', 'Jose']}
|
12
12
|
#
|
13
13
|
# @param [Array] column_names
|
14
14
|
# @return [Hash]
|
@@ -32,11 +32,11 @@ module ElasticsearchRecord
|
|
32
32
|
# For a single column_name a hash with the distinct key and the +doc_count+ as value is returned.
|
33
33
|
# For multiple column_names a hash with the distinct keys (as hash) and the +doc_count+ as value is returned.
|
34
34
|
#
|
35
|
-
#
|
36
|
-
#
|
35
|
+
# Person.composite(:name)
|
36
|
+
# #> {"David" => 10, "Jeremy" => 1, "Jose" => 24}
|
37
37
|
#
|
38
|
-
#
|
39
|
-
#
|
38
|
+
# Person.composite(:name, :age)
|
39
|
+
# #> {
|
40
40
|
# {name: "David", age: "16"} => 3,
|
41
41
|
# {name: "David", age: "18"} => 6,
|
42
42
|
# {name: "David", age: "20"} => 1,
|
@@ -89,7 +89,7 @@ module ElasticsearchRecord
|
|
89
89
|
# @param [String] keep_alive - how long to keep alive (for each single request) - default: '1m'
|
90
90
|
# @param [Integer] batch_size - how many results per query (default: 1000 - this means at least 10 queries before reaching the +max_result_window+)
|
91
91
|
def pit_results(keep_alive: '1m', batch_size: 1000)
|
92
|
-
raise ArgumentError, "Batch size cannot be above the 'max_result_window' (#{klass.
|
92
|
+
raise ArgumentError, "Batch size cannot be above the 'max_result_window' (#{klass.max_result_window}) !" if batch_size > klass.max_result_window
|
93
93
|
|
94
94
|
# check if a limit or offset values was provided
|
95
95
|
results_limit = limit_value ? limit_value : Float::INFINITY
|
@@ -182,6 +182,12 @@ module ElasticsearchRecord
|
|
182
182
|
spawn.aggs_only!.resolve('Aggregations').aggregations
|
183
183
|
end
|
184
184
|
|
185
|
+
# returns the response aggregations and resolve the buckets as key->value hash.
|
186
|
+
# @return [ActiveSupport::HashWithIndifferentAccess, Hash]
|
187
|
+
def buckets
|
188
|
+
spawn.aggs_only!.resolve('Buckets').buckets
|
189
|
+
end
|
190
|
+
|
185
191
|
# returns the RAW hits for the current query
|
186
192
|
# @return [Array]
|
187
193
|
def hits
|
@@ -48,9 +48,8 @@ module ElasticsearchRecord
|
|
48
48
|
response.key?('hits') ? response['hits'].with_indifferent_access : {}
|
49
49
|
end
|
50
50
|
|
51
|
-
# Returns the RAW
|
51
|
+
# Returns the RAW +_source+ data from each hit - aka. +rows+.
|
52
52
|
# PLEASE NOTE: The array will only contain the RAW data from each +_source+ (meta info like '_score' is not included)
|
53
|
-
# The +rows+ alias use used by the ActiveRecord ConnectionAdapters and must not be removed!
|
54
53
|
# @return [Array]
|
55
54
|
def results
|
56
55
|
return [] unless response['hits']
|
@@ -58,6 +57,7 @@ module ElasticsearchRecord
|
|
58
57
|
response['hits']['hits'].map { |result| result['_source'] }
|
59
58
|
end
|
60
59
|
|
60
|
+
# The +rows+ alias is used by the ActiveRecord ConnectionAdapters and must not be removed!
|
61
61
|
alias_method :rows, :results
|
62
62
|
|
63
63
|
# returns the response RAW aggregations hash.
|
@@ -66,6 +66,31 @@ module ElasticsearchRecord
|
|
66
66
|
response.key?('aggregations') ? response['aggregations'].with_indifferent_access : {}
|
67
67
|
end
|
68
68
|
|
69
|
+
# returns the (nested) bucket values (and aggregated values) from the response aggregations.
|
70
|
+
# @return [ActiveSupport::HashWithIndifferentAccess]
|
71
|
+
def buckets
|
72
|
+
# aggregations are already a hash with key => data, but to prevent reference manipulation on the hash
|
73
|
+
# we have to create a new one here...
|
74
|
+
aggregations.reduce({}) { |buckets, (key, agg)|
|
75
|
+
# check if this agg has a bucket
|
76
|
+
if agg.key?(:buckets)
|
77
|
+
buckets[key] = agg[:buckets].reduce({}) { |m, b|
|
78
|
+
# buckets can be a Hash or Array (of Hashes)
|
79
|
+
bucket_key, bucket = b.is_a?(Hash) ? [b[:key], b] : b
|
80
|
+
m[bucket_key] = bucket.except(:key, :doc_count).transform_values { |val| val[:value] }
|
81
|
+
|
82
|
+
m
|
83
|
+
}
|
84
|
+
elsif agg.key?(:value)
|
85
|
+
buckets[key] = agg[:value]
|
86
|
+
elsif agg.key?(:values)
|
87
|
+
buckets[key] = agg[:values]
|
88
|
+
end
|
89
|
+
|
90
|
+
buckets
|
91
|
+
}.with_indifferent_access
|
92
|
+
end
|
93
|
+
|
69
94
|
# Returns true if this result set includes the column named +name+.
|
70
95
|
# used by ActiveRecord
|
71
96
|
def includes_column?(name)
|
@@ -119,9 +144,10 @@ module ElasticsearchRecord
|
|
119
144
|
n ? computed_results.last(n) : computed_results.last
|
120
145
|
end
|
121
146
|
|
122
|
-
#
|
123
|
-
|
124
|
-
|
147
|
+
# returns the response result string
|
148
|
+
# @return [String]
|
149
|
+
def result
|
150
|
+
response['result'] || ''
|
125
151
|
end
|
126
152
|
|
127
153
|
# used by ActiveRecord
|
@@ -176,6 +202,7 @@ module ElasticsearchRecord
|
|
176
202
|
return self.response['total'] if self.response.key?('total')
|
177
203
|
return self.response['hits']['total']['value'] if self.response.key?('hits')
|
178
204
|
return self.response['aggregations'].count if self.response.key?('aggregations')
|
205
|
+
return self.response['_shards']['total'] if self.response.key?('_shards')
|
179
206
|
|
180
207
|
0
|
181
208
|
end
|
@@ -37,7 +37,8 @@ module ElasticsearchRecord
|
|
37
37
|
if ActiveModel::Attribute === value
|
38
38
|
value = value.value_for_database
|
39
39
|
end
|
40
|
-
|
40
|
+
value
|
41
|
+
# connection.quote(value)
|
41
42
|
elsif thing.is_a?(Hash)
|
42
43
|
thing.transform_values { |val|
|
43
44
|
deep_substitute_binds(val, binds, connection)
|
data/lib/elasticsearch_record.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# VERSION
|
4
3
|
require_relative 'elasticsearch_record/version'
|
4
|
+
require_relative "elasticsearch_record/errors"
|
5
5
|
|
6
6
|
require 'active_record'
|
7
7
|
|
@@ -27,7 +27,6 @@ module ElasticsearchRecord
|
|
27
27
|
autoload :Querying
|
28
28
|
autoload :Query
|
29
29
|
autoload :Result
|
30
|
-
autoload :SchemaMigration
|
31
30
|
autoload :StatementCache
|
32
31
|
end
|
33
32
|
|
@@ -59,6 +58,7 @@ end
|
|
59
58
|
ActiveSupport.on_load(:active_record) do
|
60
59
|
# load patches
|
61
60
|
require 'elasticsearch_record/patches/active_record/relation_merger_patch'
|
61
|
+
|
62
62
|
require 'elasticsearch_record/patches/arel/select_core_patch'
|
63
63
|
require 'elasticsearch_record/patches/arel/select_manager_patch'
|
64
64
|
require 'elasticsearch_record/patches/arel/select_statement_patch'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elasticsearch_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Gonsior
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -53,33 +53,33 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0
|
61
|
+
version: '13.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0
|
68
|
+
version: '13.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: yard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '0.9'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '0.9'
|
83
83
|
description: 'ElasticsearchRecord is a ActiveRecord adapter and provides similar functionality
|
84
84
|
for Elasticsearch.
|
85
85
|
|
@@ -91,7 +91,7 @@ extensions: []
|
|
91
91
|
extra_rdoc_files: []
|
92
92
|
files:
|
93
93
|
- ".rspec"
|
94
|
-
- ".
|
94
|
+
- ".yardopts"
|
95
95
|
- Gemfile
|
96
96
|
- Gemfile.lock
|
97
97
|
- README.md
|
@@ -99,16 +99,30 @@ files:
|
|
99
99
|
- docs/CHANGELOG.md
|
100
100
|
- docs/CODE_OF_CONDUCT.md
|
101
101
|
- docs/LICENSE.txt
|
102
|
+
- elasticsearch_record.gemspec
|
102
103
|
- lib/active_record/connection_adapters/elasticsearch/column.rb
|
103
104
|
- lib/active_record/connection_adapters/elasticsearch/database_statements.rb
|
104
105
|
- lib/active_record/connection_adapters/elasticsearch/quoting.rb
|
106
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_creation.rb
|
107
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions.rb
|
108
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions/attribute_methods.rb
|
109
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions/column_methods.rb
|
110
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions/create_table_definition.rb
|
111
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_alias_definition.rb
|
112
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb
|
113
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_mapping_definition.rb
|
114
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_setting_definition.rb
|
115
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_definitions/update_table_definition.rb
|
116
|
+
- lib/active_record/connection_adapters/elasticsearch/schema_dumper.rb
|
105
117
|
- lib/active_record/connection_adapters/elasticsearch/schema_statements.rb
|
118
|
+
- lib/active_record/connection_adapters/elasticsearch/table_statements.rb
|
106
119
|
- lib/active_record/connection_adapters/elasticsearch/type.rb
|
107
120
|
- lib/active_record/connection_adapters/elasticsearch/type/format_string.rb
|
108
121
|
- lib/active_record/connection_adapters/elasticsearch/type/multicast_value.rb
|
109
122
|
- lib/active_record/connection_adapters/elasticsearch/type/nested.rb
|
110
123
|
- lib/active_record/connection_adapters/elasticsearch/type/object.rb
|
111
124
|
- lib/active_record/connection_adapters/elasticsearch/type/range.rb
|
125
|
+
- lib/active_record/connection_adapters/elasticsearch/unsupported_implementation.rb
|
112
126
|
- lib/active_record/connection_adapters/elasticsearch_adapter.rb
|
113
127
|
- lib/arel/collectors/elasticsearch_query.rb
|
114
128
|
- lib/arel/nodes/select_agg.rb
|
@@ -116,9 +130,13 @@ files:
|
|
116
130
|
- lib/arel/nodes/select_kind.rb
|
117
131
|
- lib/arel/nodes/select_query.rb
|
118
132
|
- lib/arel/visitors/elasticsearch.rb
|
133
|
+
- lib/arel/visitors/elasticsearch_base.rb
|
134
|
+
- lib/arel/visitors/elasticsearch_query.rb
|
135
|
+
- lib/arel/visitors/elasticsearch_schema.rb
|
119
136
|
- lib/elasticsearch_record.rb
|
120
137
|
- lib/elasticsearch_record/base.rb
|
121
138
|
- lib/elasticsearch_record/core.rb
|
139
|
+
- lib/elasticsearch_record/errors.rb
|
122
140
|
- lib/elasticsearch_record/extensions/relation.rb
|
123
141
|
- lib/elasticsearch_record/gem_version.rb
|
124
142
|
- lib/elasticsearch_record/instrumentation.rb
|
@@ -143,7 +161,6 @@ files:
|
|
143
161
|
- lib/elasticsearch_record/relation/result_methods.rb
|
144
162
|
- lib/elasticsearch_record/relation/value_methods.rb
|
145
163
|
- lib/elasticsearch_record/result.rb
|
146
|
-
- lib/elasticsearch_record/schema_migration.rb
|
147
164
|
- lib/elasticsearch_record/statement_cache.rb
|
148
165
|
- lib/elasticsearch_record/tasks/elasticsearch_database_tasks.rb
|
149
166
|
- lib/elasticsearch_record/version.rb
|
@@ -155,6 +172,7 @@ metadata:
|
|
155
172
|
allowed_push_host: https://rubygems.org
|
156
173
|
homepage_uri: https://github.com/ruby-smart/elasticsearch_record
|
157
174
|
source_code_uri: https://github.com/ruby-smart/elasticsearch_record
|
175
|
+
documentation_uri: https://rubydoc.info/gems/elasticsearch_record
|
158
176
|
changelog_uri: https://github.com/ruby-smart/elasticsearch_record/blob/main/docs/CHANGELOG.md
|
159
177
|
post_install_message:
|
160
178
|
rdoc_options: []
|
@@ -171,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
189
|
- !ruby/object:Gem::Version
|
172
190
|
version: '0'
|
173
191
|
requirements: []
|
174
|
-
rubygems_version: 3.
|
192
|
+
rubygems_version: 3.2.22
|
175
193
|
signing_key:
|
176
194
|
specification_version: 4
|
177
195
|
summary: ActiveRecord adapter for Elasticsearch
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
3.1.2
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'active_record/schema_migration'
|
3
|
-
|
4
|
-
module ElasticsearchRecord
|
5
|
-
# temporary workaround
|
6
|
-
# toDo: fixme
|
7
|
-
class SchemaMigration < ActiveRecord::SchemaMigration # :nodoc:
|
8
|
-
class << self
|
9
|
-
def create_table
|
10
|
-
$stdout.puts "\n>>> 'create_table' elasticsearch is not supported - the following message is insignificant!"
|
11
|
-
end
|
12
|
-
|
13
|
-
def drop_table
|
14
|
-
$stdout.puts "\n>>> 'drop_table' elasticsearch is not supported - the following message is insignificant!"
|
15
|
-
end
|
16
|
-
|
17
|
-
def normalized_versions
|
18
|
-
[]
|
19
|
-
end
|
20
|
-
|
21
|
-
def all_versions
|
22
|
-
[]
|
23
|
-
end
|
24
|
-
|
25
|
-
def table_exists?
|
26
|
-
true
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|