stretchy-model 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -1
  3. data/README.md +28 -10
  4. data/Rakefile +56 -0
  5. data/docs/.nojekyll +0 -0
  6. data/docs/README.md +147 -0
  7. data/docs/_coverpage.md +14 -0
  8. data/docs/_sidebar.md +15 -0
  9. data/docs/examples/_sidebar.md +15 -0
  10. data/docs/examples/data_analysis.md +216 -0
  11. data/docs/examples/neural_search_with_llm.md +381 -0
  12. data/docs/examples/simple-ingest-pipeline.md +326 -0
  13. data/docs/guides/_sidebar.md +15 -0
  14. data/docs/guides/aggregations.md +142 -0
  15. data/docs/guides/machine-learning.md +154 -0
  16. data/docs/guides/models.md +372 -0
  17. data/docs/guides/pipelines.md +151 -0
  18. data/docs/guides/querying.md +361 -0
  19. data/docs/guides/quick-start.md +72 -0
  20. data/docs/guides/scopes.md +125 -0
  21. data/docs/index.html +113 -0
  22. data/docs/stretchy.cover.png +0 -0
  23. data/docs/stretchy.logo.png +0 -0
  24. data/docs/styles.css +90 -0
  25. data/lib/elasticsearch/api/actions/connector/check_in.rb +64 -0
  26. data/lib/elasticsearch/api/actions/connector/delete.rb +64 -0
  27. data/lib/elasticsearch/api/actions/connector/get.rb +64 -0
  28. data/lib/elasticsearch/api/actions/connector/last_sync.rb +66 -0
  29. data/lib/elasticsearch/api/actions/connector/list.rb +60 -0
  30. data/lib/elasticsearch/api/actions/connector/post.rb +57 -0
  31. data/lib/elasticsearch/api/actions/connector/put.rb +66 -0
  32. data/lib/elasticsearch/api/actions/connector/update_api_key_id.rb +66 -0
  33. data/lib/elasticsearch/api/actions/connector/update_configuration.rb +66 -0
  34. data/lib/elasticsearch/api/actions/connector/update_error.rb +66 -0
  35. data/lib/elasticsearch/api/actions/connector/update_filtering.rb +66 -0
  36. data/lib/elasticsearch/api/actions/connector/update_index_name.rb +66 -0
  37. data/lib/elasticsearch/api/actions/connector/update_name.rb +66 -0
  38. data/lib/elasticsearch/api/actions/connector/update_native.rb +66 -0
  39. data/lib/elasticsearch/api/actions/connector/update_pipeline.rb +66 -0
  40. data/lib/elasticsearch/api/actions/connector/update_scheduling.rb +66 -0
  41. data/lib/elasticsearch/api/actions/connector/update_service_type.rb +66 -0
  42. data/lib/elasticsearch/api/actions/connector/update_status.rb +66 -0
  43. data/lib/elasticsearch/api/namespace/connector.rb +36 -0
  44. data/lib/opensearch/api/actions/machine_learning/connector/delete.rb +42 -0
  45. data/lib/opensearch/api/actions/machine_learning/connector/get.rb +42 -0
  46. data/lib/opensearch/api/actions/machine_learning/connector/list.rb +38 -0
  47. data/lib/opensearch/api/actions/machine_learning/connector/post.rb +35 -0
  48. data/lib/opensearch/api/actions/machine_learning/connector/put.rb +44 -0
  49. data/lib/opensearch/api/actions/machine_learning/models/predict.rb +32 -0
  50. data/lib/opensearch/api/namespace/connector.rb +19 -0
  51. data/lib/stretchy/attributes/transformers/keyword_transformer.rb +41 -35
  52. data/lib/stretchy/attributes/type/array.rb +24 -1
  53. data/lib/stretchy/attributes/type/base.rb +6 -2
  54. data/lib/stretchy/attributes/type/binary.rb +24 -17
  55. data/lib/stretchy/attributes/type/boolean.rb +29 -22
  56. data/lib/stretchy/attributes/type/completion.rb +18 -10
  57. data/lib/stretchy/attributes/type/constant_keyword.rb +35 -26
  58. data/lib/stretchy/attributes/type/date_time.rb +28 -17
  59. data/lib/stretchy/attributes/type/dense_vector.rb +46 -49
  60. data/lib/stretchy/attributes/type/flattened.rb +28 -19
  61. data/lib/stretchy/attributes/type/geo_point.rb +21 -12
  62. data/lib/stretchy/attributes/type/geo_shape.rb +21 -12
  63. data/lib/stretchy/attributes/type/hash.rb +24 -10
  64. data/lib/stretchy/attributes/type/histogram.rb +25 -0
  65. data/lib/stretchy/attributes/type/ip.rb +26 -17
  66. data/lib/stretchy/attributes/type/join.rb +16 -7
  67. data/lib/stretchy/attributes/type/keyword.rb +21 -26
  68. data/lib/stretchy/attributes/type/knn_vector.rb +47 -0
  69. data/lib/stretchy/attributes/type/match_only_text.rb +22 -1
  70. data/lib/stretchy/attributes/type/nested.rb +16 -11
  71. data/lib/stretchy/attributes/type/numeric/base.rb +30 -22
  72. data/lib/stretchy/attributes/type/numeric/byte.rb +20 -0
  73. data/lib/stretchy/attributes/type/numeric/double.rb +20 -0
  74. data/lib/stretchy/attributes/type/numeric/float.rb +20 -0
  75. data/lib/stretchy/attributes/type/numeric/half_float.rb +20 -0
  76. data/lib/stretchy/attributes/type/numeric/integer.rb +21 -1
  77. data/lib/stretchy/attributes/type/numeric/long.rb +20 -0
  78. data/lib/stretchy/attributes/type/numeric/scaled_float.rb +16 -7
  79. data/lib/stretchy/attributes/type/numeric/short.rb +20 -0
  80. data/lib/stretchy/attributes/type/numeric/unsigned_long.rb +21 -1
  81. data/lib/stretchy/attributes/type/percolator.rb +16 -4
  82. data/lib/stretchy/attributes/type/point.rb +19 -9
  83. data/lib/stretchy/attributes/type/range/base.rb +24 -1
  84. data/lib/stretchy/attributes/type/range/date_range.rb +21 -5
  85. data/lib/stretchy/attributes/type/range/double_range.rb +20 -4
  86. data/lib/stretchy/attributes/type/range/float_range.rb +21 -5
  87. data/lib/stretchy/attributes/type/range/integer_range.rb +20 -4
  88. data/lib/stretchy/attributes/type/range/ip_range.rb +20 -4
  89. data/lib/stretchy/attributes/type/range/long_range.rb +20 -4
  90. data/lib/stretchy/attributes/type/rank_feature.rb +16 -6
  91. data/lib/stretchy/attributes/type/rank_features.rb +16 -9
  92. data/lib/stretchy/attributes/type/search_as_you_type.rb +28 -18
  93. data/lib/stretchy/attributes/type/shape.rb +19 -9
  94. data/lib/stretchy/attributes/type/sparse_vector.rb +25 -21
  95. data/lib/stretchy/attributes/type/string.rb +42 -1
  96. data/lib/stretchy/attributes/type/text.rb +53 -28
  97. data/lib/stretchy/attributes/type/token_count.rb +21 -11
  98. data/lib/stretchy/attributes/type/version.rb +16 -6
  99. data/lib/stretchy/attributes/type/wildcard.rb +36 -25
  100. data/lib/stretchy/attributes.rb +29 -0
  101. data/lib/stretchy/delegation/gateway_delegation.rb +78 -0
  102. data/lib/stretchy/index_setting.rb +94 -0
  103. data/lib/stretchy/indexing/bulk.rb +75 -3
  104. data/lib/stretchy/machine_learning/connector.rb +130 -0
  105. data/lib/stretchy/machine_learning/errors.rb +25 -0
  106. data/lib/stretchy/machine_learning/model.rb +162 -109
  107. data/lib/stretchy/machine_learning/registry.rb +19 -0
  108. data/lib/stretchy/model/callbacks.rb +1 -0
  109. data/lib/stretchy/model/common.rb +157 -0
  110. data/lib/stretchy/model/persistence.rb +144 -0
  111. data/lib/stretchy/model/refreshable.rb +26 -0
  112. data/lib/stretchy/open_search_compatibility.rb +2 -0
  113. data/lib/stretchy/pipeline.rb +2 -1
  114. data/lib/stretchy/pipelines/processor.rb +40 -36
  115. data/lib/stretchy/querying.rb +7 -8
  116. data/lib/stretchy/rails/railtie.rb +11 -0
  117. data/lib/stretchy/rails/tasks/connector/create.rake +32 -0
  118. data/lib/stretchy/rails/tasks/connector/delete.rake +27 -0
  119. data/lib/stretchy/rails/tasks/connector/status.rake +31 -0
  120. data/lib/stretchy/rails/tasks/connector/update.rake +32 -0
  121. data/lib/stretchy/rails/tasks/index/create.rake +28 -0
  122. data/lib/stretchy/rails/tasks/index/delete.rake +27 -0
  123. data/lib/stretchy/rails/tasks/index/status.rake +23 -0
  124. data/lib/stretchy/rails/tasks/ml/delete.rake +25 -0
  125. data/lib/stretchy/rails/tasks/ml/deploy.rake +78 -0
  126. data/lib/stretchy/rails/tasks/ml/status.rake +31 -0
  127. data/lib/stretchy/rails/tasks/pipeline/create.rake +27 -0
  128. data/lib/stretchy/rails/tasks/pipeline/delete.rake +26 -0
  129. data/lib/stretchy/rails/tasks/pipeline/status.rake +25 -0
  130. data/lib/stretchy/rails/tasks/status.rake +15 -0
  131. data/lib/stretchy/rails/tasks/stretchy.rake +42 -0
  132. data/lib/stretchy/record.rb +5 -4
  133. data/lib/stretchy/relation.rb +229 -28
  134. data/lib/stretchy/relations/aggregation_methods/aggregation.rb +59 -0
  135. data/lib/stretchy/relations/aggregation_methods/avg.rb +45 -0
  136. data/lib/stretchy/relations/aggregation_methods/bucket_script.rb +47 -0
  137. data/lib/stretchy/relations/aggregation_methods/bucket_selector.rb +47 -0
  138. data/lib/stretchy/relations/aggregation_methods/bucket_sort.rb +47 -0
  139. data/lib/stretchy/relations/aggregation_methods/cardinality.rb +47 -0
  140. data/lib/stretchy/relations/aggregation_methods/children.rb +47 -0
  141. data/lib/stretchy/relations/aggregation_methods/composite.rb +41 -0
  142. data/lib/stretchy/relations/aggregation_methods/date_histogram.rb +53 -0
  143. data/lib/stretchy/relations/aggregation_methods/date_range.rb +53 -0
  144. data/lib/stretchy/relations/aggregation_methods/extended_stats.rb +48 -0
  145. data/lib/stretchy/relations/aggregation_methods/filter.rb +47 -0
  146. data/lib/stretchy/relations/aggregation_methods/filters.rb +47 -0
  147. data/lib/stretchy/relations/aggregation_methods/geo_bounds.rb +40 -0
  148. data/lib/stretchy/relations/aggregation_methods/geo_centroid.rb +40 -0
  149. data/lib/stretchy/relations/aggregation_methods/global.rb +39 -0
  150. data/lib/stretchy/relations/aggregation_methods/histogram.rb +43 -0
  151. data/lib/stretchy/relations/aggregation_methods/ip_range.rb +41 -0
  152. data/lib/stretchy/relations/aggregation_methods/max.rb +40 -0
  153. data/lib/stretchy/relations/aggregation_methods/min.rb +41 -0
  154. data/lib/stretchy/relations/aggregation_methods/missing.rb +40 -0
  155. data/lib/stretchy/relations/aggregation_methods/nested.rb +40 -0
  156. data/lib/stretchy/relations/aggregation_methods/percentile_ranks.rb +45 -0
  157. data/lib/stretchy/relations/aggregation_methods/percentiles.rb +45 -0
  158. data/lib/stretchy/relations/aggregation_methods/range.rb +42 -0
  159. data/lib/stretchy/relations/aggregation_methods/reverse_nested.rb +40 -0
  160. data/lib/stretchy/relations/aggregation_methods/sampler.rb +40 -0
  161. data/lib/stretchy/relations/aggregation_methods/scripted_metric.rb +43 -0
  162. data/lib/stretchy/relations/aggregation_methods/significant_terms.rb +45 -0
  163. data/lib/stretchy/relations/aggregation_methods/stats.rb +42 -0
  164. data/lib/stretchy/relations/aggregation_methods/sum.rb +42 -0
  165. data/lib/stretchy/relations/aggregation_methods/terms.rb +46 -0
  166. data/lib/stretchy/relations/aggregation_methods/top_hits.rb +42 -0
  167. data/lib/stretchy/relations/aggregation_methods/top_metrics.rb +44 -0
  168. data/lib/stretchy/relations/aggregation_methods/value_count.rb +41 -0
  169. data/lib/stretchy/relations/aggregation_methods/weighted_avg.rb +42 -0
  170. data/lib/stretchy/relations/aggregation_methods.rb +20 -749
  171. data/lib/stretchy/relations/finder_methods.rb +2 -18
  172. data/lib/stretchy/relations/null_relation.rb +55 -0
  173. data/lib/stretchy/relations/query_builder.rb +82 -36
  174. data/lib/stretchy/relations/query_methods/bind.rb +19 -0
  175. data/lib/stretchy/relations/query_methods/extending.rb +29 -0
  176. data/lib/stretchy/relations/query_methods/fields.rb +70 -0
  177. data/lib/stretchy/relations/query_methods/filter_query.rb +53 -0
  178. data/lib/stretchy/relations/query_methods/has_field.rb +40 -0
  179. data/lib/stretchy/relations/query_methods/highlight.rb +75 -0
  180. data/lib/stretchy/relations/query_methods/hybrid.rb +60 -0
  181. data/lib/stretchy/relations/query_methods/ids.rb +40 -0
  182. data/lib/stretchy/relations/query_methods/match.rb +52 -0
  183. data/lib/stretchy/relations/query_methods/must_not.rb +54 -0
  184. data/lib/stretchy/relations/query_methods/neural.rb +58 -0
  185. data/lib/stretchy/relations/query_methods/neural_sparse.rb +43 -0
  186. data/lib/stretchy/relations/query_methods/none.rb +21 -0
  187. data/lib/stretchy/relations/query_methods/or_filter.rb +21 -0
  188. data/lib/stretchy/relations/query_methods/order.rb +63 -0
  189. data/lib/stretchy/relations/query_methods/query_string.rb +44 -0
  190. data/lib/stretchy/relations/query_methods/regexp.rb +61 -0
  191. data/lib/stretchy/relations/query_methods/should.rb +51 -0
  192. data/lib/stretchy/relations/query_methods/size.rb +44 -0
  193. data/lib/stretchy/relations/query_methods/skip_callbacks.rb +47 -0
  194. data/lib/stretchy/relations/query_methods/source.rb +59 -0
  195. data/lib/stretchy/relations/query_methods/where.rb +113 -0
  196. data/lib/stretchy/relations/query_methods.rb +48 -569
  197. data/lib/stretchy/relations/scoping/default.rb +136 -0
  198. data/lib/stretchy/relations/scoping/named.rb +70 -0
  199. data/lib/stretchy/relations/scoping/scope_registry.rb +36 -0
  200. data/lib/stretchy/relations/scoping.rb +30 -0
  201. data/lib/stretchy/relations/search_option_methods.rb +2 -0
  202. data/lib/stretchy/version.rb +1 -1
  203. data/lib/stretchy.rb +24 -10
  204. metadata +170 -17
  205. data/lib/stretchy/common.rb +0 -38
  206. data/lib/stretchy/null_relation.rb +0 -53
  207. data/lib/stretchy/persistence.rb +0 -43
  208. data/lib/stretchy/refreshable.rb +0 -15
  209. data/lib/stretchy/scoping/default.rb +0 -134
  210. data/lib/stretchy/scoping/named.rb +0 -68
  211. data/lib/stretchy/scoping/scope_registry.rb +0 -34
  212. data/lib/stretchy/scoping.rb +0 -28
@@ -1,6 +1,9 @@
1
+ require 'stretchy/machine_learning/errors'
2
+
1
3
  module Stretchy
2
4
  module MachineLearning
3
5
  class Model
6
+
4
7
  PRETRAINED_MODELS = {
5
8
  :neural_sparse => {
6
9
  :encoding => 'amazon/neural-sparse/opensearch-neural-sparse-encoding-v1',
@@ -31,7 +34,165 @@ module Stretchy
31
34
  end
32
35
 
33
36
  class << self
34
- attr_accessor :model, :group_id
37
+ include Errors
38
+ # delegate :find, :status, :deployed?, :registered?, :task_id, :deploy_id, :model_id, :register, :deploy, :undeploy, :delete, to: :model
39
+
40
+ METHODS = [
41
+ :model,
42
+ :group_id,
43
+ :version,
44
+ :description,
45
+ :model_format,
46
+ :enabled,
47
+ :connector_id,
48
+ :connector,
49
+ :function_name,
50
+ :model_config,
51
+ :model_content_hash_value,
52
+ :url
53
+ ]
54
+
55
+ def settings
56
+ @settings ||= {}
57
+ end
58
+
59
+ METHODS.each do |method|
60
+ define_method(method) do |args = nil|
61
+ return settings[method] unless args.present?
62
+ settings[method] = args
63
+
64
+ if method == :connector
65
+ connector_class = "#{args.to_s.camelize}".constantize
66
+ settings[:connector] = connector_class
67
+ # raise ConnectorMissingError if connector_class.id.nil?
68
+ settings[:connector_id] = connector_class.id
69
+ end
70
+
71
+ if method == :model
72
+ settings[:model] = model_lookup(args)
73
+ end
74
+ end
75
+ end
76
+
77
+ def model_id
78
+ @model_id || registry.model_id
79
+ end
80
+
81
+ def task_id
82
+ @task_id || registry.register_task_id
83
+ end
84
+
85
+ def deploy_id
86
+ @deploy_id || registry.deploy_task_id
87
+ end
88
+
89
+
90
+ def registry
91
+ @registry ||= Stretchy::MachineLearning::Registry.register(class_name: self.name, class_type: 'model')
92
+ end
93
+
94
+ def register
95
+ begin
96
+
97
+ response = client.register(body: self.to_hash, deploy: true)
98
+
99
+ @task_id = response['task_id']
100
+
101
+ self.registry.update(register_task_id: @task_id)
102
+
103
+ yield self if block_given?
104
+
105
+ registered?
106
+ self.registry.update(model_id: @model_id)
107
+ @model_id
108
+ rescue => e
109
+ Stretchy.logger.error "Error registering model: #{e.message}"
110
+ false
111
+ end
112
+ true
113
+ end
114
+
115
+ def registered?
116
+ return false unless task_id
117
+ response = status
118
+ @model_id = response['model_id'] if response['model_id']
119
+ response['state'] == 'COMPLETED' && @model_id.present?
120
+ end
121
+
122
+ def status
123
+ client.get_status(task_id: self.task_id)
124
+ end
125
+
126
+
127
+ def deploy
128
+ @deployed = nil
129
+
130
+ @deploy_id = client.deploy(id: self.model_id)['task_id']
131
+ self.registry.update(deploy_task_id: @deploy_id)
132
+ yield self if block_given?
133
+ @deploy_id
134
+ end
135
+
136
+ def undeploy
137
+ @deployed = nil
138
+ response = client.undeploy(id: self.model_id)
139
+ self.registry.update(deploy_task_id: nil)
140
+ yield self if block_given?
141
+ response
142
+ end
143
+
144
+ def deployed?
145
+ return @deployed if @deployed
146
+ response = client.get_model(id: self.model_id)
147
+ # raise "Model not deployed" if response['model_state'] == 'FAILED'
148
+ @deployed = response['model_state'] == 'DEPLOYED'
149
+ end
150
+
151
+ def delete
152
+ self.registry.delete
153
+ client.delete_model(id: self.model_id)
154
+ end
155
+
156
+ def find
157
+ begin
158
+ client.get_model(id: self.model_id)
159
+ rescue "#{Stretchy.configuration.search_backend_const}::Transport::Transport::Errors::InternalServerError".constantize => e
160
+ raise Stretchy::MachineLearning::Errors::ModelMissingError
161
+ end
162
+ end
163
+
164
+ def model_name(model_name = nil)
165
+ @model_name = model_name if model_name
166
+ @model_name || to_s.demodulize.underscore
167
+ end
168
+
169
+ def to_hash
170
+ {
171
+ name: self.model || self.model_name,
172
+ model_group_id: self.group_id,
173
+ version: self.version,
174
+ description: self.description,
175
+ model_format: self.model_format,
176
+ is_enabled: self.enabled?,
177
+ connector_id: self.connector.present? ? self.connector.id : nil,
178
+ function_name: self.function_name
179
+ }.compact
180
+ end
181
+
182
+ def enabled?
183
+ self.enabled
184
+ end
185
+
186
+ def wait_until_complete(max_attempts: 20, sleep_time: 4)
187
+ attempts = 0
188
+ loop do
189
+ result = yield
190
+ break if result
191
+ attempts += 1
192
+ break if attempts >= max_attempts
193
+ sleep(sleep_time)
194
+ end
195
+ end
35
196
 
36
197
  def all
37
198
  client.get_model
@@ -78,114 +239,6 @@ module Stretchy
78
239
  end
79
240
  end
80
241
 
81
- attr_accessor :model,
82
- :group_id,
83
- :version,
84
- :description,
85
- :model_format,
86
- :enabled,
87
- :connector_id,
88
- :connector,
89
- :function_name,
90
- :model_config,
91
- :model_content_hash_value,
92
- :url
93
-
94
- attr_reader :task_id, :model_id, :deploy_id
95
-
96
- def initialize(args = {})
97
- model_name = args.delete(:model)
98
- args.each do |k,v|
99
- self.send("#{k}=", v)
100
- end
101
- @model = self.class.model_lookup model_name
102
- end
103
-
104
- def register
105
- begin
106
- response = client.register(body: self.to_hash, deploy: true)
107
-
108
- @task_id = response['task_id']
109
-
110
- yield self if block_given?
111
-
112
- @model_id
113
- rescue => e
114
- Stretchy.logger.error "Error registering model: #{e.message}"
115
- false
116
- end
117
- true
118
- end
119
-
120
- def registered?
121
- response = status
122
- @model_id = response['model_id'] if response['model_id']
123
- response['state'] == 'COMPLETED' && @model_id.present?
124
- end
125
-
126
- def status
127
- client.get_status(task_id: self.task_id)
128
- end
129
-
130
- def deploy
131
- @deployed = nil
132
- @deploy_id = client.deploy(id: self.model_id)['task_id']
133
- yield self if block_given?
134
- @deploy_id
135
- end
136
-
137
- def undeploy
138
- @deployed = nil
139
- response = client.undeploy(id: self.model_id)
140
- yield self if block_given?
141
- response
142
- end
143
-
144
- def deployed?
145
- return @deployed if @deployed
146
- response = client.get_model(id: self.model_id)
147
- # raise "Model not deployed" if response['model_state'] == 'FAILED'
148
- @deployed = response['model_state'] == 'DEPLOYED'
149
- end
150
-
151
- def delete
152
- client.delete_model(id: self.model_id)
153
- end
154
-
155
- def client
156
- @@client
157
- end
158
-
159
- def find
160
- client.get_model(id: self.model_id)
161
- end
162
-
163
- def to_hash
164
- {
165
- name: self.model,
166
- model_group_id: self.group_id,
167
- version: self.version,
168
- description: self.description,
169
- model_format: self.model_format,
170
- is_enabled: self.enabled?
171
- }.compact
172
- end
173
-
174
- def enabled?
175
- self.enabled
176
- end
177
-
178
- def wait_until_complete(max_attempts: 20, sleep_time: 4)
179
- attempts = 0
180
- loop do
181
- result = yield
182
- break if result
183
- attempts += 1
184
- break if attempts >= max_attempts
185
- sleep(sleep_time)
186
- end
187
- end
188
-
189
242
 
190
243
  end
191
244
  end
@@ -0,0 +1,19 @@
1
+ module Stretchy::MachineLearning
2
+ class Registry < StretchyModel
3
+
4
+ index_name ".stretchy_ml_registry_#{Stretchy.env}"
5
+
6
+ attribute :model_id, :keyword
7
+ attribute :model_group_id, :keyword
8
+ attribute :deploy_task_id, :keyword
9
+ attribute :register_task_id, :keyword
10
+ attribute :class_name, :keyword
11
+ attribute :class_type, :keyword
12
+
13
+ def self.register(**args)
14
+ self.create_index! unless index_exists?
15
+ where(class_name: args[:class_name]).first || create(**args)
16
+ end
17
+
18
+ end
19
+ end
@@ -8,6 +8,7 @@ module Stretchy
8
8
  included do
9
9
  mattr_accessor :_circuit_breaker_callbacks, default: []
10
10
 
11
+ define_model_callbacks :initialize, only: :after
11
12
  define_model_callbacks :create, :save, :update, :destroy
12
13
  define_model_callbacks :find, :touch, only: :after
13
14
  end
@@ -0,0 +1,157 @@
1
+ module Stretchy
2
+ module Model
3
+ module Common
4
+ extend ActiveSupport::Concern
5
+
6
+ # Get the highlighted results for a specific field.
7
+ #
8
+ # This method is used to get the highlighted results for a specific field from the search results. It accepts a field for which to get the highlighted results.
9
+ #
10
+ # ### Parameters
11
+ #
12
+ # - `field:` The Symbol or String representing the field for which to get the highlighted results.
13
+ #
14
+ # ### Returns
15
+ # Returns an Array of Strings representing the highlighted results for the specified field.
16
+ #
17
+ # ---
18
+ #
19
+ # ### Examples
20
+ #
21
+ # #### Get the highlighted results for a field
22
+ #
23
+ # ```ruby
24
+ # result = Model.query_string("name: Soph*").highlight(name: {pre_tags: "__", post_tags: "__"}).first
25
+ # result.highlights_for(:name)
26
+ # ```
27
+ #
28
+ def highlights_for(attribute)
29
+ highlights[attribute.to_s]
30
+ end
31
+
32
+ class_methods do
33
+
34
+ # Set or get the default sort key.
35
+ #
36
+ # This method is used to set or get the default sort key to be used in sort operations. If a field is provided, it sets the field as the default sort key. If no field is provided, it returns the current default sort key.
37
+ #
38
+ # `created_at` is the default sort key.
39
+ #
40
+ # ### Parameters
41
+ #
42
+ # - `field:` The Symbol or String representing the field to be used as the default sort key (optional).
43
+ #
44
+ # ### Returns
45
+ # Returns the current default sort key if no field is provided. If a field is provided, it sets the field as the default sort key and returns the field.
46
+ #
47
+ # ---
48
+ #
49
+ # ### Examples
50
+ #
51
+ # #### Set the default sort key
52
+ #
53
+ # ```ruby
54
+ # class Model < StretchyModel
55
+ # default_sort_key :updated_at
56
+ # end
57
+ # ```
58
+ #
59
+ # #### Get the default sort key
60
+ #
61
+ # ```ruby
62
+ # Model.default_sort_key
63
+ # ```
64
+ #
65
+ def default_sort_key(field = nil)
66
+ @default_sort_key = field unless field.nil?
67
+ @default_sort_key
68
+ end
69
+
70
+
71
+ # Set or get the default size.
72
+ #
73
+ # This method is used to set or get the default size to be used in operations that return documents. If a size is provided, it sets the size as the default size.
74
+ # If no size is provided, it returns the current default size.
75
+ #
76
+ # 10000 is the default size for StretchyModel
77
+ #
78
+ # ### Parameters
79
+ #
80
+ # - `size:` The Integer representing the size to be used as the default size (optional).
81
+ #
82
+ # ### Returns
83
+ # Returns the current default size if no size is provided. If a size is provided, it sets the size as the default size and returns the size.
84
+ #
85
+ # ---
86
+ #
87
+ # ### Examples
88
+ #
89
+ # #### Set the default size
90
+ #
91
+ # ```ruby
92
+ # class Model < StretchyModel
93
+ # default_size 100
94
+ # end
95
+ # ```
96
+ #
97
+ # #### Get the default size
98
+ #
99
+ # ```ruby
100
+ # Model.default_size
101
+ # ```
102
+ #
103
+ def default_size(size = nil)
104
+ @default_size = size unless size.nil?
105
+ @default_size
106
+ end
107
+
108
+
109
+ # Set or get the default pipeline.
110
+ #
111
+ # This method is used to set or get the default pipeline at the index level to be used in operations that require a pipeline.
112
+ #
113
+ # If a pipeline is provided, it sets the pipeline as the default pipeline.
114
+ # If no pipeline is provided, it returns the current default pipeline.
115
+ #
116
+ # ### Parameters
117
+ #
118
+ # - `pipeline:` The String representing the pipeline to be used as the default pipeline (optional).
119
+ #
120
+ # ### Returns
121
+ # Returns the current default pipeline if no pipeline is provided. If a pipeline is provided, it sets the pipeline as the default pipeline and returns the pipeline.
122
+ #
123
+ # ---
124
+ #
125
+ # ### Examples
126
+ #
127
+ # #### Set the default pipeline
128
+ #
129
+ # ```ruby
130
+ # class Model < StretchyModel
131
+ # default_pipeline 'my_pipeline'
132
+ # end
133
+ # ```
134
+ #
135
+ # #### Get the default pipeline
136
+ #
137
+ # ```ruby
138
+ # Model.default_pipeline
139
+ # ```
140
+ #
141
+ def default_pipeline(pipeline = nil)
142
+ @default_pipeline = pipeline.to_s unless pipeline.nil?
143
+ @default_pipeline
144
+ end
145
+
146
+ private
147
+
148
+ # Return a Relation instance to chain queries
149
+ #
150
+ def relation
151
+ Relation.create(self, {})
152
+ end
153
+
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,144 @@
1
+ module Stretchy
2
+ module Model
3
+ module Persistence
4
+ extend ActiveSupport::Concern
5
+
6
+ class_methods do
7
+ # Create a new instance and save it to the database.
8
+ #
9
+ # This class method is used to create a new instance of the model and save it to the database. It accepts a list of keyword attributes to set on the new instance.
10
+ #
11
+ # ### Parameters
12
+ #
13
+ # - `*args:` A list of keyword arguments representing the attributes to set on the new instance.
14
+ #
15
+ # ### Returns
16
+ # Returns the newly created instance of the model.
17
+ #
18
+ # ---
19
+ #
20
+ # ### Examples
21
+ #
22
+ # #### Create a new instance
23
+ #
24
+ # ```ruby
25
+ # Model.create(name: 'John Doe', age: 30)
26
+ # ```
27
+ #
28
+ def create(*args)
29
+ self.new(*args).save
30
+ end
31
+ end
32
+
33
+ # Save the current instance to the database.
34
+ #
35
+ # This instance method is used to save the current instance of the model to the database. If the instance is a new record, it runs the `:create` callbacks and saves the instance to the database. It then sets the `id` of the instance to the `_id` returned by the save operation.
36
+ #
37
+ # ### Returns
38
+ # Returns the `id` of the saved instance.
39
+ #
40
+ # ---
41
+ #
42
+ # ### Examples
43
+ #
44
+ # #### Save an instance
45
+ #
46
+ # ```ruby
47
+ # model = Model.new(name: 'John Doe', age: 30)
48
+ # model.save
49
+ # ```
50
+ #
51
+ def save
52
+ run_callbacks :save do
53
+ if new_record?
54
+ run_callbacks :create do
55
+ response = self.class.gateway.save(self.attributes)
56
+ self.id = response['_id']
57
+ end
58
+ else
59
+ self.class.gateway.save(self.attributes)
60
+ end
61
+ self
62
+ end
63
+ end
64
+
65
+ # Destroy the current instance.
66
+ #
67
+ # This instance method is used to delete the current instance of the model from the database.
68
+ # It differs from delete in that it runs the `:destroy` callbacks before deleting the instance.
69
+ #
70
+ #
71
+ # ### Returns
72
+ # Returns `true` if the instance was successfully deleted, `false` otherwise.
73
+ #
74
+ # ---
75
+ #
76
+ # ### Examples
77
+ #
78
+ # #### Delete an instance
79
+ #
80
+ # ```ruby
81
+ # model = Model.find(id: '1')
82
+ # model.destroy
83
+ # ```
84
+ #
85
+ def destroy
86
+ run_callbacks :destroy do
87
+ delete
88
+ end
89
+ end
90
+
91
+ # Delete the current instance from the database.
92
+ #
93
+ # This instance method is used to delete the current instance of the model from the database. It uses the `id` of the instance to perform the delete operation.
94
+ #
95
+ # ### Returns
96
+ # Returns `true` if the instance was successfully deleted, `false` otherwise.
97
+ #
98
+ # ---
99
+ #
100
+ # ### Examples
101
+ #
102
+ # #### Delete an instance
103
+ #
104
+ # ```ruby
105
+ # model = Model.find(id: '1')
106
+ # model.delete
107
+ # ```
108
+ #
109
+ def delete
110
+ self.class.gateway.delete(self.id)["result"] == 'deleted'
111
+ end
112
+
113
+ # Update the current instance with the given attributes and save it to the database.
114
+ #
115
+ # This instance method is used to update the current instance of the model with the given attributes and save it to the database. It accepts a list of keyword arguments representing the attributes to update.
116
+ #
117
+ # ### Parameters
118
+ #
119
+ # - `*args:` A list of keyword arguments representing the attributes to update.
120
+ #
121
+ # ### Returns
122
+ # Returns `true` if the instance was successfully updated, `false` otherwise.
123
+ #
124
+ # ---
125
+ #
126
+ # ### Examples
127
+ #
128
+ # #### Update an instance
129
+ #
130
+ # ```ruby
131
+ # model = Model.find(id: '1')
132
+ # model.update(name: 'Jane Doe', age: 32)
133
+ # ```
134
+ #
135
+ def update(*args)
136
+ run_callbacks :update do
137
+ self.assign_attributes(*args)
138
+ self.save
139
+ end
140
+ end
141
+
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,26 @@
1
+ module Stretchy
2
+ module Model
3
+ # Adds callbacks to the model to refresh the index after save or destroy.
4
+ #
5
+ # ```ruby
6
+ # included do
7
+ # after_save :refresh_index
8
+ # after_destroy :refresh_index
9
+ # end
10
+ # ```
11
+ module Refreshable
12
+ extend ActiveSupport::Concern
13
+
14
+
15
+ included do
16
+ after_save :refresh_index
17
+ after_destroy :refresh_index
18
+ end
19
+
20
+ def refresh_index
21
+ self.class.refresh_index!
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -1,4 +1,5 @@
1
1
  require 'opensearch/api/namespace/machine_learning/model'
2
+ require 'opensearch/api/namespace/connector'
2
3
 
3
4
  module Stretchy
4
5
  module OpenSearchCompatibility
@@ -82,6 +83,7 @@ module Stretchy
82
83
  ::Elasticsearch::Persistence::Repository.send(:include, patch)
83
84
  ::Elasticsearch::Persistence::Repository.send(:include, store)
84
85
  OpenSearch::API.send(:include, OpenSearch::API::MachineLearning::Models)
86
+ OpenSearch::API.send(:include, OpenSearch::API::Connector)
85
87
 
86
88
  end
87
89
 
@@ -30,7 +30,8 @@ module Stretchy
30
30
  end
31
31
  end
32
32
 
33
- def find(id)
33
+ def find(id=nil)
34
+ id = self.pipeline_name if id.nil?
34
35
  client.get_pipeline(id: id)
35
36
  end
36
37