elasticsearch_record 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +4 -0
  3. data/Gemfile.lock +10 -14
  4. data/README.md +180 -27
  5. data/docs/CHANGELOG.md +36 -18
  6. data/docs/LICENSE.txt +1 -1
  7. data/elasticsearch_record.gemspec +42 -0
  8. data/lib/active_record/connection_adapters/elasticsearch/column.rb +20 -6
  9. data/lib/active_record/connection_adapters/elasticsearch/database_statements.rb +142 -125
  10. data/lib/active_record/connection_adapters/elasticsearch/quoting.rb +2 -23
  11. data/lib/active_record/connection_adapters/elasticsearch/schema_creation.rb +30 -0
  12. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/attribute_methods.rb +103 -0
  13. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/column_methods.rb +42 -0
  14. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/create_table_definition.rb +158 -0
  15. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_alias_definition.rb +32 -0
  16. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_definition.rb +132 -0
  17. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_mapping_definition.rb +110 -0
  18. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/table_setting_definition.rb +136 -0
  19. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions/update_table_definition.rb +174 -0
  20. data/lib/active_record/connection_adapters/elasticsearch/schema_definitions.rb +37 -0
  21. data/lib/active_record/connection_adapters/elasticsearch/schema_dumper.rb +110 -0
  22. data/lib/active_record/connection_adapters/elasticsearch/schema_statements.rb +398 -174
  23. data/lib/active_record/connection_adapters/elasticsearch/table_statements.rb +232 -0
  24. data/lib/active_record/connection_adapters/elasticsearch/type/multicast_value.rb +2 -0
  25. data/lib/active_record/connection_adapters/elasticsearch/unsupported_implementation.rb +32 -0
  26. data/lib/active_record/connection_adapters/elasticsearch_adapter.rb +112 -19
  27. data/lib/arel/collectors/elasticsearch_query.rb +0 -1
  28. data/lib/arel/visitors/elasticsearch.rb +7 -579
  29. data/lib/arel/visitors/elasticsearch_base.rb +234 -0
  30. data/lib/arel/visitors/elasticsearch_query.rb +463 -0
  31. data/lib/arel/visitors/elasticsearch_schema.rb +124 -0
  32. data/lib/elasticsearch_record/core.rb +44 -10
  33. data/lib/elasticsearch_record/errors.rb +13 -0
  34. data/lib/elasticsearch_record/gem_version.rb +6 -2
  35. data/lib/elasticsearch_record/instrumentation/log_subscriber.rb +27 -9
  36. data/lib/elasticsearch_record/model_schema.rb +5 -0
  37. data/lib/elasticsearch_record/persistence.rb +31 -26
  38. data/lib/elasticsearch_record/query.rb +56 -17
  39. data/lib/elasticsearch_record/querying.rb +17 -0
  40. data/lib/elasticsearch_record/relation/calculation_methods.rb +3 -0
  41. data/lib/elasticsearch_record/relation/core_methods.rb +57 -17
  42. data/lib/elasticsearch_record/relation/query_clause_tree.rb +38 -1
  43. data/lib/elasticsearch_record/relation/query_methods.rb +6 -0
  44. data/lib/elasticsearch_record/relation/result_methods.rb +15 -9
  45. data/lib/elasticsearch_record/result.rb +32 -5
  46. data/lib/elasticsearch_record/statement_cache.rb +2 -1
  47. data/lib/elasticsearch_record.rb +2 -2
  48. metadata +29 -11
  49. data/.ruby-version +0 -1
  50. 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
@@ -223,6 +223,12 @@ module ElasticsearchRecord
223
223
  self
224
224
  end
225
225
 
226
+ def or!(other)
227
+ self.query_clause = self.query_clause.or(other.query_clause)
228
+
229
+ super(other)
230
+ end
231
+
226
232
  def unscope!(*args)
227
233
  # :nodoc:
228
234
  self.unscope_values += args
@@ -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
- # Person.agg_pluck(:name)
8
- # => {"name" => ['David', 'Jeremy', 'Jose']}
7
+ # Person.agg_pluck(:name)
8
+ # #> {"name" => ['David', 'Jeremy', 'Jose']}
9
9
  #
10
- # Person.agg_pluck(:id, :name)
11
- # => {"id" => ['11', '2', '5'], "name" => ['David', 'Jeremy', 'Jose']}
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
- # Person.composite(:name)
36
- # => {"David" => 10, "Jeremy" => 1, "Jose" => 24}
35
+ # Person.composite(:name)
36
+ # #> {"David" => 10, "Jeremy" => 1, "Jose" => 24}
37
37
  #
38
- # Person.composite(:name, :age)
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.connection.max_result_window}) !" if batch_size > klass.connection.max_result_window
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 values from the hits - aka. +rows+.
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
- # used by ActiveRecord
123
- def result # :nodoc:
124
- self
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
- connection.quote(value)
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)
@@ -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.2
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-07 00:00:00.000000000 Z
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: simplecov
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.21'
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.21'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rake
70
+ name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '13.0'
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: '13.0'
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
- - ".ruby-version"
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.3.7
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