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.
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