Skip to content

Commit

Permalink
Fix Add mapping defaults and options to attributes #73
Browse files Browse the repository at this point in the history
  • Loading branch information
esmarkowski committed Mar 15, 2024
1 parent 4b74564 commit eb68986
Show file tree
Hide file tree
Showing 51 changed files with 1,031 additions and 54 deletions.
2 changes: 1 addition & 1 deletion lib/stretchy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
require_relative "rails/instrumentation/railtie" if defined?(Rails)



module Stretchy

def self.loader
Expand All @@ -21,6 +20,7 @@ def self.loader
loader.tag = File.basename(__FILE__, ".rb")
loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
loader.push_dir(__dir__)
loader.inflector.inflect("ip" => "IP")
loader
end
end
Expand Down
44 changes: 44 additions & 0 deletions lib/stretchy/attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,59 @@ def inspect
def inspect
"#<#{self.name} #{attribute_types.map { |k,v| "#{k}: #{v.type}" }.join(', ')}>"
end

def attribute_mappings
{properties: attribute_types.map { |k,v| v.mappings(k) }.reduce({}, :merge)}.as_json
end
end

def self.register!
ActiveModel::Type.register(:array, Stretchy::Attributes::Type::Array)
ActiveModel::Type.register(:binary, Stretchy::Attributes::Type::Binary)
ActiveModel::Type.register(:boolean, Stretchy::Attributes::Type::Boolean)
ActiveModel::Type.register(:constant_keyword, Stretchy::Attributes::Type::ConstantKeyword)
ActiveModel::Type.register(:datetime, Stretchy::Attributes::Type::DateTime)
ActiveModel::Type.register(:flattened, Stretchy::Attributes::Type::Flattened)
ActiveModel::Type.register(:geo_point, Stretchy::Attributes::Type::GeoPoint)
ActiveModel::Type.register(:geo_shape, Stretchy::Attributes::Type::GeoShape)
ActiveModel::Type.register(:histogram, Stretchy::Attributes::Type::Histogram)
ActiveModel::Type.register(:hash, Stretchy::Attributes::Type::Hash)
ActiveModel::Type.register(:ip, Stretchy::Attributes::Type::IP)
ActiveModel::Type.register(:join, Stretchy::Attributes::Type::Join)
ActiveModel::Type.register(:keyword, Stretchy::Attributes::Type::Keyword)
ActiveModel::Type.register(:match_only_text, Stretchy::Attributes::Type::MatchOnlyText)
ActiveModel::Type.register(:nested, Stretchy::Attributes::Type::Nested)
ActiveModel::Type.register(:percolator, Stretchy::Attributes::Type::Percolator)
ActiveModel::Type.register(:point, Stretchy::Attributes::Type::Point)
ActiveModel::Type.register(:rank_feature, Stretchy::Attributes::Type::RankFeature)

ActiveModel::Type.register(:text, Stretchy::Attributes::Type::Text)
ActiveModel::Type.register(:token_count, Stretchy::Attributes::Type::TokenCount)
ActiveModel::Type.register(:dense_vector, Stretchy::Attributes::Type::DenseVector)

ActiveModel::Type.register(:search_as_you_type, Stretchy::Attributes::Type::SearchAsYouType)
ActiveModel::Type.register(:sparse_vector, Stretchy::Attributes::Type::SparseVector)
ActiveModel::Type.register(:string, Stretchy::Attributes::Type::String)
ActiveModel::Type.register(:version, Stretchy::Attributes::Type::Version)
ActiveModel::Type.register(:wildcard, Stretchy::Attributes::Type::Wildcard)
# Numerics
ActiveModel::Type.register(:long, Stretchy::Attributes::Type::Numeric::Long)
ActiveModel::Type.register(:integer, Stretchy::Attributes::Type::Numeric::Integer)
ActiveModel::Type.register(:short, Stretchy::Attributes::Type::Numeric::Short)
ActiveModel::Type.register(:byte, Stretchy::Attributes::Type::Numeric::Byte)
ActiveModel::Type.register(:double, Stretchy::Attributes::Type::Numeric::Double)
ActiveModel::Type.register(:float, Stretchy::Attributes::Type::Numeric::Float)
ActiveModel::Type.register(:half_float, Stretchy::Attributes::Type::Numeric::HalfFloat)
ActiveModel::Type.register(:scaled_float, Stretchy::Attributes::Type::Numeric::ScaledFloat)
ActiveModel::Type.register(:unsigned_long, Stretchy::Attributes::Type::Numeric::UnsignedLong)
# Ranges
ActiveModel::Type.register(:integer_range, Stretchy::Attributes::Type::Range::IntegerRange)
ActiveModel::Type.register(:float_range, Stretchy::Attributes::Type::Range::FloatRange)
ActiveModel::Type.register(:long_range, Stretchy::Attributes::Type::Range::LongRange)
ActiveModel::Type.register(:double_range, Stretchy::Attributes::Type::Range::DoubleRange)
ActiveModel::Type.register(:date_range, Stretchy::Attributes::Type::Range::DateRange)
ActiveModel::Type.register(:ip_range, Stretchy::Attributes::Type::Range::IpRange)

end
end
end
18 changes: 5 additions & 13 deletions lib/stretchy/attributes/type/array.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
module Stretchy
module Attributes
module Type

class Array < ActiveModel::Type::Value # :nodoc:

def type
:array
end

end

end
module Stretchy::Attributes::Type
class Array < Stretchy::Attributes::Type::Base # :nodoc:
def type
:array
end
end
end
38 changes: 38 additions & 0 deletions lib/stretchy/attributes/type/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module Stretchy
module Attributes
module Type
class Base < ActiveModel::Type::Value

OPTIONS = []


def initialize(**args)

define_option_methods!

args.each do |k, v|
if self.class::OPTIONS.include?(k)
instance_variable_set("@#{k}", v)
args.delete(k)
end
end
super
end

def mappings(name)
options = {type: type}
self.class::OPTIONS.each { |option| options[option] = send(option) unless send(option).nil? }
{ name => options }.as_json
end

private

def define_option_methods!
self.class::OPTIONS.each do |option|
define_singleton_method(option.to_sym) { instance_variable_get("@#{option}") }
end
end
end
end
end
end
45 changes: 45 additions & 0 deletions lib/stretchy/attributes/type/binary.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Public: Defines a binary attribute for the model.
#
# name - The Symbol name of the attribute.
# opts - The Hash options used to refine the attribute (default: {}):
# :doc_values - The Boolean indicating if the field should be stored on disk in a column-stride fashion.
# This allows it to be used later for sorting, aggregations, or scripting. Defaults to false.
# :store - The Boolean indicating if the field value should be stored and retrievable separately from the _source field. Defaults to false.
#
# Examples
#
# class MyModel
# include StretchyModel
# attribute :name, :binary, doc_values: true, store: true
# end
#
# Returns nothing.
module Stretchy
module Attributes
module Type
class Binary < ActiveModel::Type::Value
OPTIONS = [:doc_values, :store]
attr_reader *OPTIONS

def initialize(**args)
args.each do |k, v|
instance_variable_set("@#{k}", v) if OPTIONS.include?(k)
args.delete(k)
end
super
end

def type
:binary
end


def mappings(name)
options = {type: type}
OPTIONS.each { |_| options[_] = self.send(_) }
{ name => options }.as_json
end
end
end
end
end
48 changes: 48 additions & 0 deletions lib/stretchy/attributes/type/boolean.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Public: Defines a boolean attribute for the model.
#
# name - The Symbol name of the attribute.
# opts - The Hash options used to refine the attribute (default: {}):
# :doc_values - The Boolean indicating if the field should be stored on disk in a column-stride fashion.
# This allows it to be used later for sorting, aggregations, or scripting. Defaults to true.
# :index - The Boolean indicating if the field should be quickly searchable. Defaults to true.
# :ignore_malformed - The Boolean indicating if exceptions thrown when trying to index the wrong data type into a field should be ignored. Defaults to false.
# :null_value - The Boolean value to be substituted for any explicit null values. Defaults to null.
# :on_script_error - The String defining what to do if the script defined by the :script parameter throws an error at indexing time. Can be 'fail' or 'continue'.
# :script - The String script that will index values generated by this script, rather than reading the values directly from the source.
# :store - The Boolean indicating if the field value should be stored and retrievable separately from the _source field. Defaults to false.
# :meta - The Hash metadata about the field.
#
# Examples
#
# class MyModel
# include StretchyModel
# attribute :name, :boolean, doc_values: true, store: true
# end
#
# Returns nothing.
module Stretchy
module Attributes
module Type
class Boolean < Stretchy::Attributes::Type::Base

OPTIONS = [:doc_values, :index, :ignore_malformed, :null_value, :on_script_error, :script, :store, :meta]
attr_reader *OPTIONS

def initialize(**args)
args.each do |k, v|
instance_variable_set("@#{k}", v) if OPTIONS.include?(k)
args.delete(k)
end
super
end

def type
:boolean
end



end
end
end
end
25 changes: 25 additions & 0 deletions lib/stretchy/attributes/type/completion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Stretchy::Attributes::Type
# Public: Defines a completion attribute for the model.
#
# opts - The Hash options used to refine the attribute (default: {}):
# :analyzer - The String index analyzer to use. Defaults to 'simple'.
# :search_analyzer - The String search analyzer to use. Defaults to the value of :analyzer.
# :preserve_separators - The Boolean indicating if separators should be preserved. Defaults to true.
# :preserve_position_increments - The Boolean indicating if position increments should be enabled. Defaults to true.
# :max_input_length - The Integer limit for the length of a single input. Defaults to 50.
#
# Examples
#
# class MyModel < Stretchy::Record
# attribute :name, :completion, analyzer: 'simple', max_input_length: 100
# end
#
# Returns nothing.
class Completion < Stretchy::Attributes::Type::Base
OPTIONS = [:analyzer, :search_analyzer, :preserve_separators, :preserve_position_increments, :max_input_length]
attr_reader *OPTIONS
def type
:completion
end
end
end
38 changes: 38 additions & 0 deletions lib/stretchy/attributes/type/constant_keyword.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module Stretchy::Attributes::Type
# Public: Defines a constant_keyword attribute for the model. This field type is a specialization of the keyword field, but it only accepts a single value.
#
# opts - The Hash options used to refine the attribute (default: {}):
# :doc_values - The Boolean indicating if the field should be stored on disk in a column-stride fashion. Defaults to true.
# :eager_global_ordinals - The Boolean indicating if global ordinals should be loaded eagerly on refresh. Defaults to false.
# :fields - The Hash of multi-fields for the same string value to be indexed in multiple ways.
# :ignore_above - The Integer limit for the length of the string. Strings longer than this limit will not be indexed. Defaults to 2147483647.
# :index - The Boolean indicating if the field should be quickly searchable. Defaults to true.
# :index_options - The String indicating what information should be stored in the index for scoring purposes. Defaults to 'docs'.
# :meta - The Hash metadata about the field.
# :norms - The Boolean indicating if field-length should be taken into account when scoring queries. Defaults to false.
# :null_value - The String value to be substituted for any explicit null values. Defaults to null.
# :on_script_error - The String defining what to do if the script defined by the :script parameter throws an error at indexing time. Can be 'fail' or 'continue'.
# :script - The String script that will index values generated by this script, rather than reading the values directly from the source.
# :store - The Boolean indicating if the field value should be stored and retrievable separately from the _source field. Defaults to false.
# :similarity - The String scoring algorithm or similarity to be used. Defaults to 'BM25'.
# :normalizer - The String pre-processor for the keyword prior to indexing. Defaults to null.
# :split_queries_on_whitespace - The Boolean indicating if full text queries should split the input on whitespace. Defaults to false.
# :time_series_dimension - The Boolean indicating if the field is a time series dimension. Defaults to false.
# :value - The String value to associate with all documents in the index.
#
# Examples
#
# class MyModel
# include StretchyModel
# attribute :status, :constant_keyword, value: 'active'
# end
#
# Returns nothing.
class ConstantKeyword < Stretchy::Attributes::Type::Keyword
OPTIONS = OPTIONS + [:value]
attr_reader *OPTIONS
def type
:constant_keyword
end
end
end
31 changes: 31 additions & 0 deletions lib/stretchy/attributes/type/date_time.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Stretchy::Attributes::Type
# Public: Defines a datetime attribute for the model.
#
# opts - The Hash options used to refine the attribute (default: {}):
# :doc_values - The Boolean indicating if the field should be stored on disk in a column-stride fashion.
# This allows it to be used later for sorting, aggregations, or scripting. Defaults to true.
# :format - The String date format(s) that can be parsed. Defaults to 'strict_date_optional_time||epoch_millis'.
# :locale - The String locale to use when parsing dates. Defaults to the ROOT locale.
# :ignore_malformed - The Boolean indicating if malformed numbers should be ignored. Defaults to false.
# :index - The Boolean indicating if the field should be quickly searchable. Defaults to true.
# :null_value - The Date value to be substituted for any explicit null values. Defaults to null.
# :on_script_error - The String defining what to do if the script defined by the :script parameter throws an error at indexing time. Can be 'fail' or 'continue'.
# :script - The String script that will index values generated by this script, rather than reading the values directly from the source.
# :store - The Boolean indicating if the field value should be stored and retrievable separately from the _source field. Defaults to false.
# :meta - The Hash metadata about the field.
#
# Examples
#
# class MyModel < Stretchy::Record
# attribute :created_at, :datetime, format: 'strict_date_optional_time||epoch_millis', locale: 'en'
# end
#
# Returns nothing.
class DateTime < Stretchy::Attributes::Type::Base
OPTIONS = [:doc_values, :format, :locale, :ignore_malformed, :index, :null_value, :on_script_error, :script, :store, :meta]
attr_reader *OPTIONS
def type
:datetime
end
end
end
4 changes: 2 additions & 2 deletions lib/stretchy/attributes/type/dense_vector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
module Stretchy
module Attributes
module Type
class DenseVector < ActiveModel::Type::Value# :nodoc:
class DenseVector < Stretchy::Attributes::Type::Base
OPTIONS = [:element_type, :dims, :index, :similarity, :index_options]
attr_reader *OPTIONS

Expand All @@ -52,7 +52,7 @@ def mappings(name)
"#{name}.tokens": options
}
}.as_json
end
end
end
end
end
Expand Down
31 changes: 31 additions & 0 deletions lib/stretchy/attributes/type/flattened.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module Stretchy::Attributes::Type
# Public: Defines a flattened attribute for the model.
#
# opts - The Hash options used to refine the attribute (default: {}):
# :depth_limit - The Integer maximum allowed depth of the flattened object field. Defaults to 20.
# :doc_values - The Boolean indicating if the field should be stored on disk in a column-stride fashion. Defaults to true.
# :eager_global_ordinals - The Boolean indicating if global ordinals should be loaded eagerly on refresh. Defaults to false.
# :ignore_above - The Integer limit for the length of leaf values. Values longer than this limit will not be indexed. By default, there is no limit.
# :index - The Boolean indicating if the field should be searchable. Defaults to true.
# :index_options - The String indicating what information should be stored in the index for scoring purposes. Defaults to 'docs'.
# :null_value - The String value to be substituted for any explicit null values. Defaults to null.
# :similarity - The String scoring algorithm or similarity to be used. Defaults to 'BM25'.
# :split_queries_on_whitespace - The Boolean indicating if full text queries should split the input on whitespace. Defaults to false.
# :time_series_dimensions - The Array of Strings indicating the fields inside the flattened object that are dimensions of the time series.
#
# Examples
#
# class MyModel
# include StretchyModel
# attribute :metadata, :flattened, depth_limit: 10, index_options: 'freqs'
# end
#
# Returns nothing.
class Flattened < Stretchy::Attributes::Type::Base
OPTIONS = [:depth_limit, :doc_values, :eager_global_ordinals, :ignore_above, :index, :index_options, :null_value, :similarity, :split_queries_on_whitespace, :time_series_dimensions]

def type
:flattened
end
end
end
Loading

0 comments on commit eb68986

Please sign in to comment.