stretchy-model 0.4.0 → 0.6.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/.rspec +1 -1
- data/README.md +19 -84
- data/lib/rails/instrumentation/railtie.rb +2 -0
- data/lib/stretchy/associations.rb +155 -15
- data/lib/stretchy/attributes/type/array.rb +20 -0
- data/lib/stretchy/attributes/type/base.rb +42 -0
- data/lib/stretchy/attributes/type/binary.rb +45 -0
- data/lib/stretchy/attributes/type/boolean.rb +48 -0
- data/lib/stretchy/attributes/type/completion.rb +25 -0
- data/lib/stretchy/attributes/type/constant_keyword.rb +38 -0
- data/lib/stretchy/attributes/type/date_time.rb +35 -0
- data/lib/stretchy/attributes/type/dense_vector.rb +59 -0
- data/lib/stretchy/attributes/type/flattened.rb +31 -0
- data/lib/stretchy/attributes/type/geo_point.rb +27 -0
- data/lib/stretchy/attributes/type/geo_shape.rb +27 -0
- data/lib/stretchy/attributes/type/hash.rb +40 -0
- data/lib/stretchy/attributes/type/histogram.rb +7 -0
- data/lib/stretchy/attributes/type/ip.rb +29 -0
- data/lib/stretchy/attributes/type/join.rb +22 -0
- data/lib/stretchy/attributes/type/keyword.rb +36 -10
- data/lib/stretchy/attributes/type/match_only_text.rb +8 -0
- data/lib/stretchy/attributes/type/nested.rb +25 -0
- data/lib/stretchy/attributes/type/numeric/base.rb +32 -0
- data/lib/stretchy/attributes/type/numeric/byte.rb +7 -0
- data/lib/stretchy/attributes/type/numeric/double.rb +7 -0
- data/lib/stretchy/attributes/type/numeric/float.rb +7 -0
- data/lib/stretchy/attributes/type/numeric/half_float.rb +7 -0
- data/lib/stretchy/attributes/type/numeric/integer.rb +7 -0
- data/lib/stretchy/attributes/type/numeric/long.rb +7 -0
- data/lib/stretchy/attributes/type/numeric/scaled_float.rb +23 -0
- data/lib/stretchy/attributes/type/numeric/short.rb +7 -0
- data/lib/stretchy/attributes/type/numeric/unsigned_long.rb +7 -0
- data/lib/stretchy/attributes/type/percolator.rb +23 -0
- data/lib/stretchy/attributes/type/point.rb +24 -0
- data/lib/stretchy/attributes/type/range/base.rb +9 -0
- data/lib/stretchy/attributes/type/range/date_range.rb +17 -0
- data/lib/stretchy/attributes/type/range/double_range.rb +17 -0
- data/lib/stretchy/attributes/type/range/float_range.rb +16 -0
- data/lib/stretchy/attributes/type/range/integer_range.rb +16 -0
- data/lib/stretchy/attributes/type/range/ip_range.rb +16 -0
- data/lib/stretchy/attributes/type/range/long_range.rb +16 -0
- data/lib/stretchy/attributes/type/rank_feature.rb +21 -0
- data/lib/stretchy/attributes/type/rank_features.rb +24 -0
- data/lib/stretchy/attributes/type/search_as_you_type.rb +30 -0
- data/lib/stretchy/attributes/type/shape.rb +24 -0
- data/lib/stretchy/attributes/type/sparse_vector.rb +37 -0
- data/lib/stretchy/attributes/type/string.rb +7 -0
- data/lib/stretchy/attributes/type/text.rb +51 -0
- data/lib/stretchy/attributes/type/token_count.rb +26 -0
- data/lib/stretchy/attributes/type/version.rb +21 -0
- data/lib/stretchy/attributes/type/wildcard.rb +35 -0
- data/lib/stretchy/attributes.rb +68 -2
- data/lib/stretchy/common.rb +5 -5
- data/lib/stretchy/delegation/gateway_delegation.rb +9 -5
- data/lib/stretchy/model/serialization.rb +1 -0
- data/lib/stretchy/querying.rb +4 -4
- data/lib/stretchy/record.rb +9 -10
- data/lib/stretchy/relation.rb +11 -17
- data/lib/stretchy/relations/finder_methods.rb +19 -2
- data/lib/stretchy/relations/merger.rb +5 -1
- data/lib/stretchy/relations/query_builder.rb +32 -3
- data/lib/stretchy/relations/query_methods.rb +66 -2
- data/lib/stretchy/scoping/named.rb +1 -1
- data/lib/stretchy/shared_scopes.rb +1 -1
- data/lib/stretchy/version.rb +1 -1
- data/lib/stretchy.rb +5 -3
- data/lib/stretchy_model.rb +9 -0
- metadata +49 -4
- data/lib/active_model/type/array.rb +0 -13
- data/lib/active_model/type/hash.rb +0 -15
@@ -0,0 +1,24 @@
|
|
1
|
+
module Stretchy::Attributes::Type
|
2
|
+
# Public: Defines a rank_features attribute for the model.
|
3
|
+
#
|
4
|
+
# A rank_features field can index numeric feature vectors, so that they can later be used to boost documents in queries with a rank_feature query.
|
5
|
+
|
6
|
+
# It is analogous to the rank_feature data type but is better suited when the list of features is sparse so that it wouldn’t be reasonable to add one field to the mappings for each of them.
|
7
|
+
# opts - The Hash options used to refine the attribute (default: {}):
|
8
|
+
# :positive_score_impact - The Boolean indicating if features correlate positively with the score. If set to false, the score decreases with the value of the feature instead of increasing. Defaults to true.
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# class MyModel < Stretchy::Record
|
13
|
+
# attribute :negative_reviews, :rank_features, positive_score_impact: false
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Returns nothing.
|
17
|
+
class RankFeatures < Stretchy::Attributes::Type::Base
|
18
|
+
OPTIONS = [:positive_score_impact]
|
19
|
+
|
20
|
+
def type
|
21
|
+
:rank_features
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Stretchy::Attributes::Type
|
2
|
+
# Public: Defines a search_as_you_type attribute for the model. This field type is optimized to provide out-of-the-box support for queries that serve an as-you-type completion use case.
|
3
|
+
#
|
4
|
+
# opts - The Hash options used to refine the attribute (default: {}):
|
5
|
+
# :max_shingle_size - The Integer indicating the largest shingle size to create. Valid values are 2 to 4. Defaults to 3.
|
6
|
+
# :analyzer - The String analyzer to be used for text fields, both at index-time and at search-time. Defaults to the default index analyzer, or the standard analyzer.
|
7
|
+
# :index - The Boolean indicating if the field should be searchable. Defaults to true.
|
8
|
+
# :index_options - The String indicating what information should be stored in the index, for search and highlighting purposes. Defaults to 'positions'.
|
9
|
+
# :norms - The Boolean indicating if field-length should be taken into account when scoring queries. Defaults to true.
|
10
|
+
# :store - The Boolean indicating if the field value should be stored and retrievable separately from the _source field. Defaults to false.
|
11
|
+
# :search_analyzer - The String analyzer that should be used at search time on text fields. Defaults to the analyzer setting.
|
12
|
+
# :search_quote_analyzer - The String analyzer that should be used at search time when a phrase is encountered. Defaults to the search_analyzer setting.
|
13
|
+
# :similarity - The String indicating which scoring algorithm or similarity should be used. Defaults to 'BM25'.
|
14
|
+
# :term_vector - The String indicating if term vectors should be stored for the field. Defaults to 'no'.
|
15
|
+
#
|
16
|
+
# Examples
|
17
|
+
#
|
18
|
+
# class MyModel < Stretchy::Record
|
19
|
+
# attribute :name, :search_as_you_type, max_shingle_size: 4
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
23
|
+
class SearchAsYouType < Stretchy::Attributes::Type::Base
|
24
|
+
OPTIONS = [:max_shingle_size, :analyzer, :index, :index_options, :norms, :store, :search_analyzer, :search_quote_analyzer, :similarity, :term_vector]
|
25
|
+
|
26
|
+
def type
|
27
|
+
:search_as_you_type
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Stretchy::Attributes::Type
|
2
|
+
# Public: Defines a shape attribute for the model. This field type is used for complex shapes.
|
3
|
+
#
|
4
|
+
# opts - The Hash options used to refine the attribute (default: {}):
|
5
|
+
# :orientation - The String indicating how to interpret vertex order for polygons / multipolygons. Can be 'right', 'ccw', 'counterclockwise', 'left', 'cw', 'clockwise'. Defaults to 'ccw'.
|
6
|
+
# :ignore_malformed - The Boolean indicating if malformed GeoJSON or WKT shapes should be ignored. Defaults to false.
|
7
|
+
# :ignore_z_value - The Boolean indicating if the z value of three dimension points should be ignored. Defaults to true.
|
8
|
+
# :coerce - The Boolean indicating if unclosed linear rings in polygons will be automatically closed. Defaults to false.
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# class MyModel < Stretchy::Record
|
13
|
+
# attribute :boundary, :shape, orientation: 'cw'
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Returns nothing.
|
17
|
+
class Shape < Stretchy::Attributes::Type::Base
|
18
|
+
OPTIONS = [:orientation, :ignore_malformed, :ignore_z_value, :coerce]
|
19
|
+
|
20
|
+
def type
|
21
|
+
:shape
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# attribute :ml, :sparse_vector
|
3
|
+
#
|
4
|
+
# {
|
5
|
+
# "mappings": {
|
6
|
+
# "properties": {
|
7
|
+
# "ml.tokens": {
|
8
|
+
# "type": "sparse_vector"
|
9
|
+
# }
|
10
|
+
# }
|
11
|
+
# }
|
12
|
+
# }
|
13
|
+
#
|
14
|
+
|
15
|
+
|
16
|
+
module Stretchy
|
17
|
+
module Attributes
|
18
|
+
module Type
|
19
|
+
class SparseVector < Stretchy::Attributes::Type::Base
|
20
|
+
|
21
|
+
def type
|
22
|
+
:sparse_vector
|
23
|
+
end
|
24
|
+
|
25
|
+
def mappings(name)
|
26
|
+
{
|
27
|
+
properties: {
|
28
|
+
"#{name}.tokens": {
|
29
|
+
type: "sparse_vector"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}.as_json
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Stretchy::Attributes::Type
|
2
|
+
# Public: Defines a text attribute for the model. This field type is used for text strings.
|
3
|
+
#
|
4
|
+
# opts - The Hash options used to refine the attribute (default: {}):
|
5
|
+
# :analyzer - The String analyzer to be used for the text field, both at index-time and at search-time. Defaults to the default index analyzer, or the standard analyzer.
|
6
|
+
# :eager_global_ordinals - The Boolean indicating if global ordinals should be loaded eagerly on refresh. Defaults to false.
|
7
|
+
# :fielddata - The Boolean indicating if the field can use in-memory fielddata for sorting, aggregations, or scripting. Defaults to false.
|
8
|
+
# :fielddata_frequency_filter - The Hash of expert settings which allow to decide which values to load in memory when fielddata is enabled.
|
9
|
+
# :fields - The Hash of multi-fields allow the same string value to be indexed in multiple ways for different purposes. By default, a 'keyword' field is added. Set to false to disable.
|
10
|
+
# :index - The Boolean indicating if the field should be searchable. Defaults to true.
|
11
|
+
# :index_options - The String indicating what information should be stored in the index, for search and highlighting purposes. Defaults to 'positions'.
|
12
|
+
# :index_prefixes - The Hash indicating if term prefixes of between 2 and 5 characters are indexed into a separate field.
|
13
|
+
# :index_phrases - The Boolean indicating if two-term word combinations (shingles) are indexed into a separate field. Defaults to false.
|
14
|
+
# :norms - The Boolean indicating if field-length should be taken into account when scoring queries. Defaults to true.
|
15
|
+
# :position_increment_gap - The Integer indicating the number of fake term position which should be inserted between each element of an array of strings. Defaults to 100.
|
16
|
+
# :store - The Boolean indicating if the field value should be stored and retrievable separately from the _source field. Defaults to false.
|
17
|
+
# :search_analyzer - The String analyzer that should be used at search time on the text field. Defaults to the analyzer setting.
|
18
|
+
# :search_quote_analyzer - The String analyzer that should be used at search time when a phrase is encountered. Defaults to the search_analyzer setting.
|
19
|
+
# :similarity - The String indicating which scoring algorithm or similarity should be used. Defaults to 'BM25'.
|
20
|
+
# :term_vector - The String indicating if term vectors should be stored for the field. Defaults to 'no'.
|
21
|
+
# :meta - The Hash of metadata about the field.
|
22
|
+
#
|
23
|
+
#
|
24
|
+
# Examples
|
25
|
+
#
|
26
|
+
# class MyModel
|
27
|
+
# include StretchyModel
|
28
|
+
# attribute :description, :text, analyzer: 'english'
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# Returns nothing.
|
32
|
+
class Text < Stretchy::Attributes::Type::Base
|
33
|
+
OPTIONS = [:analyzer, :eager_global_ordinals, :fielddata, :fielddata_frequency_filter, :fields, :index, :index_options, :index_prefixes, :index_phrases, :norms, :position_increment_gap, :store, :search_analyzer, :search_quote_analyzer, :similarity, :term_vector, :meta]
|
34
|
+
|
35
|
+
def type
|
36
|
+
:text
|
37
|
+
end
|
38
|
+
|
39
|
+
def type_for_database
|
40
|
+
:text
|
41
|
+
end
|
42
|
+
|
43
|
+
def mappings(name)
|
44
|
+
options = {type: type_for_database}
|
45
|
+
OPTIONS.each { |option| options[option] = send(option) unless send(option).nil? }
|
46
|
+
options.delete(:fields) if fields == false
|
47
|
+
options[:fields] = {keyword: {type: :keyword, ignore_above: 256}} if fields.nil?
|
48
|
+
{ name => options }.as_json
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Stretchy::Attributes::Type
|
2
|
+
# Public: Defines a token_count attribute for the model. This field type is used for counting the number of tokens in a string.
|
3
|
+
#
|
4
|
+
# opts - The Hash options used to refine the attribute (default: {}):
|
5
|
+
# :analyzer - The String analyzer to be used to analyze the string value. Required.
|
6
|
+
# :enable_position_increments - The Boolean indicating if position increments should be counted. Defaults to true.
|
7
|
+
# :doc_values - The Boolean indicating if the field should be stored on disk in a column-stride fashion. Defaults to true.
|
8
|
+
# :index - The Boolean indicating if the field should be searchable. Defaults to true.
|
9
|
+
# :null_value - The Numeric value to be substituted for any explicit null values. Defaults to null.
|
10
|
+
# :store - The Boolean indicating if the field value should be stored and retrievable separately from the _source field. Defaults to false.
|
11
|
+
#
|
12
|
+
# Examples
|
13
|
+
#
|
14
|
+
# class MyModel < Stretchy::Record
|
15
|
+
# attribute :description_token_count, :token_count, analyzer: 'standard'
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# Returns nothing.
|
19
|
+
class TokenCount < Stretchy::Attributes::Type::Base
|
20
|
+
OPTIONS = [:analyzer, :enable_position_increments, :doc_values, :index, :null_value, :store]
|
21
|
+
|
22
|
+
def type
|
23
|
+
:token_count
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Stretchy::Attributes::Type
|
2
|
+
# Public: Defines a version attribute for the model. This field type is used for software versions following the Semantic Versioning rules.
|
3
|
+
#
|
4
|
+
# opts - The Hash options used to refine the attribute (default: {}):
|
5
|
+
# :meta - The Hash of metadata about the field.
|
6
|
+
#
|
7
|
+
# Examples
|
8
|
+
#
|
9
|
+
# class MyModel < Stretchy::Record
|
10
|
+
# attribute :software_version, :version
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# Returns nothing.
|
14
|
+
class Version < Stretchy::Attributes::Type::Base
|
15
|
+
OPTIONS = [:meta]
|
16
|
+
|
17
|
+
def type
|
18
|
+
:version
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Stretchy::Attributes::Type
|
2
|
+
# Public: Defines a wildcard attribute for the model. This field type is a specialization of the keyword field, but it supports wildcard searches.
|
3
|
+
#
|
4
|
+
# opts - The Hash options used to refine the attribute (default: {}):
|
5
|
+
# :doc_values - The Boolean indicating if the field should be stored on disk in a column-stride fashion. Defaults to true.
|
6
|
+
# :eager_global_ordinals - The Boolean indicating if global ordinals should be loaded eagerly on refresh. Defaults to false.
|
7
|
+
# :fields - The Hash of multi-fields for the same string value to be indexed in multiple ways.
|
8
|
+
# :ignore_above - The Integer limit for the length of the string. Strings longer than this limit will not be indexed. Defaults to 2147483647.
|
9
|
+
# :index - The Boolean indicating if the field should be quickly searchable. Defaults to true.
|
10
|
+
# :index_options - The String indicating what information should be stored in the index for scoring purposes. Defaults to 'docs'.
|
11
|
+
# :meta - The Hash metadata about the field.
|
12
|
+
# :norms - The Boolean indicating if field-length should be taken into account when scoring queries. Defaults to false.
|
13
|
+
# :null_value - The String value to be substituted for any explicit null values. Defaults to null.
|
14
|
+
# :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'.
|
15
|
+
# :script - The String script that will index values generated by this script, rather than reading the values directly from the source.
|
16
|
+
# :store - The Boolean indicating if the field value should be stored and retrievable separately from the _source field. Defaults to false.
|
17
|
+
# :similarity - The String scoring algorithm or similarity to be used. Defaults to 'BM25'.
|
18
|
+
# :normalizer - The String pre-processor for the keyword prior to indexing. Defaults to null.
|
19
|
+
# :split_queries_on_whitespace - The Boolean indicating if full text queries should split the input on whitespace. Defaults to false.
|
20
|
+
# :time_series_dimension - The Boolean indicating if the field is a time series dimension. Defaults to false.
|
21
|
+
#
|
22
|
+
# Examples
|
23
|
+
#
|
24
|
+
# class MyModel
|
25
|
+
# include StretchyModel
|
26
|
+
# attribute :description_wildcard, :wildcard
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# Returns nothing.
|
30
|
+
class Wildcard < Stretchy::Attributes::Type::Keyword
|
31
|
+
def type
|
32
|
+
:wildcard
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/stretchy/attributes.rb
CHANGED
@@ -1,10 +1,76 @@
|
|
1
1
|
module Stretchy
|
2
2
|
module Attributes
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def [](attribute)
|
6
|
+
self.send(attribute)
|
7
|
+
end
|
8
|
+
|
9
|
+
def []=(attribute, value)
|
10
|
+
self.send("#{attribute}=", value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
"#<#{self.class.name} #{attributes.map { |k,v| "#{k}: #{v.blank? ? 'nil' : v}" }.join(', ')}>"
|
15
|
+
end
|
16
|
+
|
17
|
+
class_methods do
|
18
|
+
def inspect
|
19
|
+
"#<#{self.name} #{attribute_types.map { |k,v| "#{k}: #{v.type}" }.join(', ')}>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def attribute_mappings
|
23
|
+
{properties: attribute_types.map { |k,v| v.mappings(k) }.reduce({}, :merge)}.as_json
|
24
|
+
end
|
25
|
+
end
|
3
26
|
|
4
27
|
def self.register!
|
5
|
-
ActiveModel::Type.register(:array,
|
6
|
-
ActiveModel::Type.register(:
|
28
|
+
ActiveModel::Type.register(:array, Stretchy::Attributes::Type::Array)
|
29
|
+
ActiveModel::Type.register(:binary, Stretchy::Attributes::Type::Binary)
|
30
|
+
ActiveModel::Type.register(:boolean, Stretchy::Attributes::Type::Boolean)
|
31
|
+
ActiveModel::Type.register(:constant_keyword, Stretchy::Attributes::Type::ConstantKeyword)
|
32
|
+
ActiveModel::Type.register(:datetime, Stretchy::Attributes::Type::DateTime)
|
33
|
+
ActiveModel::Type.register(:flattened, Stretchy::Attributes::Type::Flattened)
|
34
|
+
ActiveModel::Type.register(:geo_point, Stretchy::Attributes::Type::GeoPoint)
|
35
|
+
ActiveModel::Type.register(:geo_shape, Stretchy::Attributes::Type::GeoShape)
|
36
|
+
ActiveModel::Type.register(:histogram, Stretchy::Attributes::Type::Histogram)
|
37
|
+
ActiveModel::Type.register(:hash, Stretchy::Attributes::Type::Hash)
|
38
|
+
ActiveModel::Type.register(:ip, Stretchy::Attributes::Type::IP)
|
39
|
+
ActiveModel::Type.register(:join, Stretchy::Attributes::Type::Join)
|
7
40
|
ActiveModel::Type.register(:keyword, Stretchy::Attributes::Type::Keyword)
|
41
|
+
ActiveModel::Type.register(:match_only_text, Stretchy::Attributes::Type::MatchOnlyText)
|
42
|
+
ActiveModel::Type.register(:nested, Stretchy::Attributes::Type::Nested)
|
43
|
+
ActiveModel::Type.register(:percolator, Stretchy::Attributes::Type::Percolator)
|
44
|
+
ActiveModel::Type.register(:point, Stretchy::Attributes::Type::Point)
|
45
|
+
ActiveModel::Type.register(:rank_feature, Stretchy::Attributes::Type::RankFeature)
|
46
|
+
|
47
|
+
ActiveModel::Type.register(:text, Stretchy::Attributes::Type::Text)
|
48
|
+
ActiveModel::Type.register(:token_count, Stretchy::Attributes::Type::TokenCount)
|
49
|
+
ActiveModel::Type.register(:dense_vector, Stretchy::Attributes::Type::DenseVector)
|
50
|
+
|
51
|
+
ActiveModel::Type.register(:search_as_you_type, Stretchy::Attributes::Type::SearchAsYouType)
|
52
|
+
ActiveModel::Type.register(:sparse_vector, Stretchy::Attributes::Type::SparseVector)
|
53
|
+
ActiveModel::Type.register(:string, Stretchy::Attributes::Type::String)
|
54
|
+
ActiveModel::Type.register(:version, Stretchy::Attributes::Type::Version)
|
55
|
+
ActiveModel::Type.register(:wildcard, Stretchy::Attributes::Type::Wildcard)
|
56
|
+
# Numerics
|
57
|
+
ActiveModel::Type.register(:long, Stretchy::Attributes::Type::Numeric::Long)
|
58
|
+
ActiveModel::Type.register(:integer, Stretchy::Attributes::Type::Numeric::Integer)
|
59
|
+
ActiveModel::Type.register(:short, Stretchy::Attributes::Type::Numeric::Short)
|
60
|
+
ActiveModel::Type.register(:byte, Stretchy::Attributes::Type::Numeric::Byte)
|
61
|
+
ActiveModel::Type.register(:double, Stretchy::Attributes::Type::Numeric::Double)
|
62
|
+
ActiveModel::Type.register(:float, Stretchy::Attributes::Type::Numeric::Float)
|
63
|
+
ActiveModel::Type.register(:half_float, Stretchy::Attributes::Type::Numeric::HalfFloat)
|
64
|
+
ActiveModel::Type.register(:scaled_float, Stretchy::Attributes::Type::Numeric::ScaledFloat)
|
65
|
+
ActiveModel::Type.register(:unsigned_long, Stretchy::Attributes::Type::Numeric::UnsignedLong)
|
66
|
+
# Ranges
|
67
|
+
ActiveModel::Type.register(:integer_range, Stretchy::Attributes::Type::Range::IntegerRange)
|
68
|
+
ActiveModel::Type.register(:float_range, Stretchy::Attributes::Type::Range::FloatRange)
|
69
|
+
ActiveModel::Type.register(:long_range, Stretchy::Attributes::Type::Range::LongRange)
|
70
|
+
ActiveModel::Type.register(:double_range, Stretchy::Attributes::Type::Range::DoubleRange)
|
71
|
+
ActiveModel::Type.register(:date_range, Stretchy::Attributes::Type::Range::DateRange)
|
72
|
+
ActiveModel::Type.register(:ip_range, Stretchy::Attributes::Type::Range::IpRange)
|
73
|
+
|
8
74
|
end
|
9
75
|
end
|
10
76
|
end
|
data/lib/stretchy/common.rb
CHANGED
@@ -2,11 +2,10 @@ module Stretchy
|
|
2
2
|
module Common
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
def
|
6
|
-
|
5
|
+
def highlights_for(attribute)
|
6
|
+
highlights[attribute.to_s]
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
9
|
class_methods do
|
11
10
|
|
12
11
|
# Set the default sort key to be used in sort operations
|
@@ -16,8 +15,9 @@ module Stretchy
|
|
16
15
|
@default_sort_key
|
17
16
|
end
|
18
17
|
|
19
|
-
def default_size(size =
|
20
|
-
@default_size = size
|
18
|
+
def default_size(size = nil)
|
19
|
+
@default_size = size unless size.nil?
|
20
|
+
@default_size
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
@@ -18,8 +18,6 @@ module Stretchy
|
|
18
18
|
:count,
|
19
19
|
to: :gateway
|
20
20
|
|
21
|
-
include Rails::Instrumentation::Publishers::Record
|
22
|
-
|
23
21
|
def index_name(name=nil, &block)
|
24
22
|
if name || block_given?
|
25
23
|
return (@index_name = name || block)
|
@@ -28,13 +26,19 @@ module Stretchy
|
|
28
26
|
if @index_name.respond_to?(:call)
|
29
27
|
@index_name.call
|
30
28
|
else
|
31
|
-
@index_name || base_class.model_name.collection
|
29
|
+
@index_name || base_class.model_name.collection.parameterize.underscore
|
32
30
|
end
|
33
31
|
end
|
34
32
|
|
33
|
+
def reload_gateway_configuration!
|
34
|
+
@gateway = nil
|
35
|
+
end
|
36
|
+
|
35
37
|
def gateway(&block)
|
36
|
-
@gateway
|
37
|
-
|
38
|
+
reload_gateway_configuration! if @gateway && @gateway.client != Stretchy.configuration.client
|
39
|
+
|
40
|
+
@gateway ||= Stretchy::Repository.create(client: Stretchy.configuration.client, index_name: index_name, klass: base_class, mapping: base_class.attribute_mappings.merge(dynamic: true))
|
41
|
+
# block.arity < 1 ? @gateway.instance_eval(&block) : block.call(@gateway) if block_given?
|
38
42
|
@gateway
|
39
43
|
end
|
40
44
|
|
@@ -9,6 +9,7 @@ module Stretchy
|
|
9
9
|
|
10
10
|
def deserialize(document)
|
11
11
|
attribs = ActiveSupport::HashWithIndifferentAccess.new(document['_source']).deep_symbolize_keys
|
12
|
+
attribs[:_highlights] = document["highlight"] if document["highlight"]
|
12
13
|
_id = __get_id_from_document(document)
|
13
14
|
attribs[:id] = _id if _id
|
14
15
|
klass.new attribs
|
data/lib/stretchy/querying.rb
CHANGED
@@ -6,13 +6,13 @@ module Stretchy
|
|
6
6
|
delegate *Stretchy::Relations::AggregationMethods::AGGREGATION_METHODS, to: :all
|
7
7
|
|
8
8
|
delegate :skip_callbacks, :routing, :search_options, to: :all
|
9
|
-
delegate :must, :must_not, :should, :where_not, :where, :filter_query, :query_string, to: :all
|
9
|
+
delegate :must, :must_not, :should, :where_not, :where, :filter_query, :query_string, :regexp, to: :all
|
10
10
|
|
11
11
|
def fetch_results(es)
|
12
|
-
|
13
|
-
base_class.search(es.to_elastic, es.search_options)
|
14
|
-
else
|
12
|
+
if es.count?
|
15
13
|
base_class.count(es.to_elastic, es.search_options)
|
14
|
+
else
|
15
|
+
base_class.search(es.to_elastic, es.search_options)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
data/lib/stretchy/record.rb
CHANGED
@@ -14,11 +14,6 @@ module Stretchy
|
|
14
14
|
include ActiveModel::Conversion
|
15
15
|
include ActiveModel::Serialization
|
16
16
|
include ActiveModel::Serializers::JSON
|
17
|
-
include ActiveModel::Validations
|
18
|
-
include ActiveModel::Validations::Callbacks
|
19
|
-
extend ActiveModel::Callbacks
|
20
|
-
|
21
|
-
|
22
17
|
|
23
18
|
include Stretchy::Model::Callbacks
|
24
19
|
include Stretchy::Indexing::Bulk
|
@@ -28,12 +23,14 @@ module Stretchy
|
|
28
23
|
include Stretchy::Common
|
29
24
|
include Stretchy::Scoping
|
30
25
|
include Stretchy::Utils
|
26
|
+
include Stretchy::SharedScopes
|
27
|
+
include Stretchy::Attributes
|
31
28
|
|
32
29
|
extend Stretchy::Delegation::DelegateCache
|
33
30
|
extend Stretchy::Querying
|
34
31
|
|
35
32
|
# Set up common attributes
|
36
|
-
attribute :id, :
|
33
|
+
attribute :id, :keyword #, default: lambda { SecureRandom.uuid }
|
37
34
|
attribute :created_at, :datetime, default: lambda { Time.now.utc }
|
38
35
|
attribute :updated_at, :datetime, default: lambda { Time.now.utc }
|
39
36
|
|
@@ -44,11 +41,13 @@ module Stretchy
|
|
44
41
|
# overriden by #size
|
45
42
|
default_size 10000
|
46
43
|
|
47
|
-
|
44
|
+
attr_accessor :highlights
|
45
|
+
|
46
|
+
def initialize(attributes = {})
|
47
|
+
@highlights = attributes.delete(:_highlights)
|
48
|
+
super(attributes)
|
49
|
+
end
|
48
50
|
|
49
|
-
def initialize(attributes = {})
|
50
|
-
self.assign_attributes(attributes) if attributes
|
51
|
-
super()
|
52
51
|
end
|
53
52
|
|
54
53
|
end
|
data/lib/stretchy/relation.rb
CHANGED
@@ -3,20 +3,16 @@ module Stretchy
|
|
3
3
|
# It provides methods for querying and manipulating the documents.
|
4
4
|
class Relation
|
5
5
|
|
6
|
-
# These methods can accept multiple values.
|
7
|
-
MULTI_VALUE_METHODS = [:order, :where, :or_filter, :filter_query, :bind, :extending, :unscope, :skip_callbacks]
|
8
|
-
|
9
|
-
# These methods can accept a single value.
|
10
|
-
SINGLE_VALUE_METHODS = [:limit, :offset, :routing, :size]
|
11
|
-
|
12
6
|
# These methods cannot be used with the `delete_all` method.
|
13
7
|
INVALID_METHODS_FOR_DELETE_ALL = [:limit, :offset]
|
14
8
|
|
15
|
-
# All value methods.
|
16
|
-
VALUE_METHODS = MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS
|
17
|
-
|
18
9
|
# Include modules.
|
19
|
-
include Relations::FinderMethods,
|
10
|
+
include Relations::FinderMethods,
|
11
|
+
Relations::SpawnMethods,
|
12
|
+
Relations::QueryMethods,
|
13
|
+
Relations::AggregationMethods,
|
14
|
+
Relations::SearchOptionMethods,
|
15
|
+
Delegation
|
20
16
|
|
21
17
|
# Getters.
|
22
18
|
attr_reader :klass, :loaded
|
@@ -32,7 +28,7 @@ module Stretchy
|
|
32
28
|
# @param values [Hash] The initial values for the relation.
|
33
29
|
def initialize(klass, values={})
|
34
30
|
@klass = klass
|
35
|
-
@values = values
|
31
|
+
@values = values.merge(default_size: klass.default_size)
|
36
32
|
@offsets = {}
|
37
33
|
@loaded = false
|
38
34
|
end
|
@@ -49,14 +45,13 @@ module Stretchy
|
|
49
45
|
#
|
50
46
|
# @return [Array] The results of the relation.
|
51
47
|
def to_a
|
52
|
-
|
53
48
|
load
|
54
49
|
@records
|
55
50
|
end
|
56
51
|
alias :results :to_a
|
57
52
|
|
58
53
|
def response
|
59
|
-
|
54
|
+
results.response
|
60
55
|
end
|
61
56
|
|
62
57
|
# Returns the results of the relation as a JSON object.
|
@@ -64,7 +59,7 @@ module Stretchy
|
|
64
59
|
# @param options [Hash] The options to pass to the `as_json` method.
|
65
60
|
# @return [Hash] The results of the relation as a JSON object.
|
66
61
|
def as_json(options = nil)
|
67
|
-
|
62
|
+
results.as_json(options)
|
68
63
|
end
|
69
64
|
|
70
65
|
# Returns the Elasticsearch query for the relation.
|
@@ -98,7 +93,6 @@ module Stretchy
|
|
98
93
|
# @return [Relation] The relation object.
|
99
94
|
def load
|
100
95
|
exec_queries unless loaded?
|
101
|
-
|
102
96
|
self
|
103
97
|
end
|
104
98
|
alias :fetch :load
|
@@ -146,8 +140,8 @@ module Stretchy
|
|
146
140
|
begin
|
147
141
|
entries = to_a.results.take([size_value.to_i + 1, 11].compact.min).map!(&:inspect)
|
148
142
|
message = {}
|
149
|
-
message = {total:
|
150
|
-
message.merge!(aggregations:
|
143
|
+
message = {total: results.total, max: results.total}
|
144
|
+
message.merge!(aggregations: response.aggregations.keys) unless response.aggregations.nil?
|
151
145
|
message = message.each_pair.collect { |k,v| "#{k}: #{v}" }
|
152
146
|
message.unshift entries.join(', ') unless entries.size.zero?
|
153
147
|
"#<#{self.class.name} #{message.join(', ')}>"
|
@@ -39,14 +39,31 @@ module Stretchy
|
|
39
39
|
self
|
40
40
|
end
|
41
41
|
|
42
|
+
# size is not permitted to the count API but queries are.
|
43
|
+
#
|
44
|
+
# if a query is supplied with `.count` then the user wants a count of the results
|
45
|
+
# matching the query
|
46
|
+
#
|
47
|
+
# however, the default_size is used to limit the number of results returned
|
48
|
+
# so we remove the size from the query and then call `.count` API
|
49
|
+
#
|
50
|
+
# but if the user supplies a limit, then we should assume they want a count of the results
|
51
|
+
# which could lead to some confusion
|
52
|
+
# suppose the user calls `.size(100).count` and the default_size is 100
|
53
|
+
# if we remove size from the query, then the count could be greater than 100
|
54
|
+
#
|
55
|
+
# I think the best way to handle this is to remove the size from the query only if it was
|
56
|
+
# applied by the default_size
|
57
|
+
# If the user supplies a limit, then we should assume they want a count of the results
|
58
|
+
#
|
59
|
+
# if size is called with a limit,
|
42
60
|
def count
|
43
|
-
return results.count if @loaded
|
61
|
+
return results.count if @loaded || @values[:size].present?
|
44
62
|
spawn.count!
|
45
63
|
end
|
46
64
|
|
47
65
|
def count!
|
48
66
|
@values[:count] = true
|
49
|
-
@values.delete(:size)
|
50
67
|
spawned = spawn
|
51
68
|
spawned.order_values.clear
|
52
69
|
spawned.results
|
@@ -7,8 +7,12 @@ module Stretchy
|
|
7
7
|
class HashMerger # :nodoc:
|
8
8
|
attr_reader :relation, :hash
|
9
9
|
|
10
|
+
VALUE_METHODS = Stretchy::Relations::QueryMethods::MULTI_VALUE_METHODS.concat(
|
11
|
+
Stretchy::Relations::QueryMethods::SINGLE_VALUE_METHODS
|
12
|
+
)
|
13
|
+
|
10
14
|
def initialize(relation, hash)
|
11
|
-
hash.assert_valid_keys(*
|
15
|
+
hash.assert_valid_keys(*VALUE_METHODS)
|
12
16
|
|
13
17
|
@relation = relation
|
14
18
|
@hash = hash
|