solrb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +69 -0
  3. data/.circleci/run-with-local-config.sh +7 -0
  4. data/.gitignore +11 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +30 -0
  7. data/.ruby-version +1 -0
  8. data/Gemfile +6 -0
  9. data/Gemfile.lock +83 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +259 -0
  12. data/Rakefile +6 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/lib/solr/commit/request.rb +15 -0
  16. data/lib/solr/configuration.rb +66 -0
  17. data/lib/solr/connection.rb +33 -0
  18. data/lib/solr/core_configuration/core_config.rb +44 -0
  19. data/lib/solr/core_configuration/core_config_builder.rb +51 -0
  20. data/lib/solr/core_configuration/dynamic_field.rb +17 -0
  21. data/lib/solr/core_configuration/field.rb +20 -0
  22. data/lib/solr/delete/request.rb +34 -0
  23. data/lib/solr/document.rb +26 -0
  24. data/lib/solr/document_collection.rb +55 -0
  25. data/lib/solr/errors/ambiguous_core_error.rb +9 -0
  26. data/lib/solr/errors/solr_query_error.rb +4 -0
  27. data/lib/solr/errors/solr_url_not_defined_error.rb +16 -0
  28. data/lib/solr/grouped_document_collection.rb +38 -0
  29. data/lib/solr/indexing/document.rb +25 -0
  30. data/lib/solr/indexing/request.rb +22 -0
  31. data/lib/solr/query/request/boost_magnitude.rb +9 -0
  32. data/lib/solr/query/request/boosting/dictionary_boost_function.rb +36 -0
  33. data/lib/solr/query/request/boosting/exists_boost_function.rb +27 -0
  34. data/lib/solr/query/request/boosting/field_value_less_than_boost_function.rb +25 -0
  35. data/lib/solr/query/request/boosting/field_value_match_boost_function.rb +24 -0
  36. data/lib/solr/query/request/boosting/geodist_function.rb +37 -0
  37. data/lib/solr/query/request/boosting/ln_function_boost.rb +28 -0
  38. data/lib/solr/query/request/boosting/numeric_field_value_match_boost_function.rb +13 -0
  39. data/lib/solr/query/request/boosting/phrase_proximity_boost.rb +27 -0
  40. data/lib/solr/query/request/boosting/ranking_field_boost_function.rb +20 -0
  41. data/lib/solr/query/request/boosting/recent_field_value_boost_function.rb +26 -0
  42. data/lib/solr/query/request/boosting/scale_function_boost.rb +28 -0
  43. data/lib/solr/query/request/boosting/textual_field_value_match_boost_function.rb +13 -0
  44. data/lib/solr/query/request/boosting.rb +46 -0
  45. data/lib/solr/query/request/edismax_adapter.rb +163 -0
  46. data/lib/solr/query/request/facet.rb +68 -0
  47. data/lib/solr/query/request/field_with_boost.rb +18 -0
  48. data/lib/solr/query/request/filter.rb +73 -0
  49. data/lib/solr/query/request/geo_filter.rb +26 -0
  50. data/lib/solr/query/request/grouping.rb +37 -0
  51. data/lib/solr/query/request/or_filter.rb +16 -0
  52. data/lib/solr/query/request/runner.rb +46 -0
  53. data/lib/solr/query/request/sorting/field.rb +16 -0
  54. data/lib/solr/query/request/sorting.rb +34 -0
  55. data/lib/solr/query/request/spellcheck.rb +74 -0
  56. data/lib/solr/query/request.rb +49 -0
  57. data/lib/solr/query/response/facet_value.rb +16 -0
  58. data/lib/solr/query/response/field_facets.rb +25 -0
  59. data/lib/solr/query/response/parser.rb +154 -0
  60. data/lib/solr/query/response/spellcheck.rb +42 -0
  61. data/lib/solr/query/response.rb +48 -0
  62. data/lib/solr/response/header.rb +25 -0
  63. data/lib/solr/response/http_status.rb +27 -0
  64. data/lib/solr/response/parser.rb +47 -0
  65. data/lib/solr/response/solr_error.rb +31 -0
  66. data/lib/solr/response.rb +52 -0
  67. data/lib/solr/support/connection_helper.rb +12 -0
  68. data/lib/solr/support/hash_extensions.rb +29 -0
  69. data/lib/solr/support/schema_helper.rb +11 -0
  70. data/lib/solr/support/string_extensions.rb +12 -0
  71. data/lib/solr/support/url_helper.rb +12 -0
  72. data/lib/solr/support.rb +5 -0
  73. data/lib/solr/testing.rb +19 -0
  74. data/lib/solr/version.rb +3 -0
  75. data/lib/solr.rb +65 -0
  76. data/solrb.gemspec +36 -0
  77. metadata +261 -0
@@ -0,0 +1,44 @@
1
+ module Solr
2
+ module CoreConfiguration
3
+ class CoreConfig
4
+ attr_reader :name, :fields
5
+
6
+ def initialize(name:, fields:, default:)
7
+ @name = name
8
+ @fields = fields
9
+ @default = default
10
+ end
11
+
12
+ def field_by_name(field_name)
13
+ fields[field_name.to_sym]
14
+ end
15
+
16
+ def default?
17
+ @default
18
+ end
19
+
20
+ def url
21
+ @url ||= File.join(Solr.configuration.url || ENV['SOLR_URL'], name.to_s).chomp('/')
22
+ end
23
+
24
+ def uri
25
+ @uri ||= Addressable::URI.parse(url)
26
+ end
27
+ end
28
+
29
+ class EnvUrlCoreConfig < CoreConfig
30
+ attr_reader :name, :fields
31
+
32
+ def initialize(name: nil, fields: {})
33
+ @name = name
34
+ @fields = fields
35
+ @default = false
36
+ end
37
+
38
+ def url
39
+ raise ArgumentError, "Solr's URL can't be nil" if ENV['SOLR_URL'].nil?
40
+ ENV['SOLR_URL']
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,51 @@
1
+ module Solr
2
+ module CoreConfiguration
3
+ class CoreConfigBuilder
4
+ attr_reader :name, :dynamic_fields, :fields_params, :default
5
+
6
+ def initialize(name: nil, default:)
7
+ @name = name
8
+ @default = default
9
+ @dynamic_fields = {}
10
+ @fields_params = {}
11
+ end
12
+
13
+ def dynamic_field(field_name, solr_name:)
14
+ dynamic_fields[field_name] = Solr::CoreConfiguration::DynamicField.new(name: field_name, solr_name: solr_name)
15
+ end
16
+
17
+ def field(field_name, params = {})
18
+ fields_params[field_name] = params
19
+ end
20
+
21
+ def build
22
+ Solr::CoreConfiguration::CoreConfig.new(
23
+ name: name,
24
+ fields: build_fields,
25
+ default: default
26
+ )
27
+ end
28
+
29
+ def get_dynamic_field(field_name, dynamic_field_name)
30
+ dynamic_field = dynamic_fields[dynamic_field_name]
31
+
32
+ if dynamic_field_name && !dynamic_field
33
+ raise "Field '#{field_name}' is mapped to an undefined dynamic field '#{dynamic_field_name}'"
34
+ end
35
+
36
+ dynamic_field
37
+ end
38
+
39
+ private
40
+
41
+ def build_fields
42
+ fields_params.each_with_object({}) do |(name, params), fields|
43
+ fields[name] =
44
+ Solr::CoreConfiguration::Field.new(name: name,
45
+ solr_name: params[:solr_name],
46
+ dynamic_field: get_dynamic_field(name, params[:dynamic_field]))
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ module Solr
2
+ module CoreConfiguration
3
+ class DynamicField
4
+ attr_reader :name, :solr_name
5
+
6
+ def initialize(name:, solr_name:)
7
+ @name = name
8
+ @solr_name = solr_name
9
+ freeze
10
+ end
11
+
12
+ def build(name)
13
+ solr_name.gsub('*', name.to_s)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module Solr
2
+ module CoreConfiguration
3
+ class Field
4
+ attr_reader :name, :dynamic_field, :solr_name
5
+
6
+ def initialize(name:, dynamic_field: nil, solr_name: nil)
7
+ @name = name
8
+ @dynamic_field = dynamic_field
9
+ @solr_name = solr_name
10
+ freeze
11
+ end
12
+
13
+ def solr_field_name
14
+ return solr_name.to_s if solr_name
15
+ return dynamic_field.build(name) if dynamic_field
16
+ name.to_s
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ module Solr
2
+ module Delete
3
+ class Request
4
+ include Solr::Support::ConnectionHelper
5
+ using Solr::Support::HashExtensions
6
+
7
+ PATH = '/update'.freeze
8
+
9
+ attr_reader :delete_command
10
+
11
+ def initialize(options = {})
12
+ options = validate_delete_options!(options)
13
+ @delete_command = { delete: options }
14
+ end
15
+
16
+ def run(commit: false)
17
+ # need to think how to move out commit data from the connection, it doesn't belong there
18
+ raw_response = connection(PATH, commit: commit).post_as_json(delete_command)
19
+ Solr::Response.from_raw_response(raw_response)
20
+ end
21
+
22
+ private
23
+
24
+ def validate_delete_options!(options)
25
+ options = options.deep_symbolize_keys
26
+ id, query = options.values_at(:id, :query)
27
+ error_message = 'options must contain either id or query, but not both'
28
+ raise ArgumentError, error_message if id.nil? && query.nil?
29
+ raise ArgumentError, error_message if id && query
30
+ options
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ module Solr
2
+ class Document
3
+ class GroupInformation
4
+ attr_reader :key, :value
5
+ def initialize(key:, value:)
6
+ @key = key
7
+ @value = value
8
+ end
9
+
10
+ def self.empty
11
+ new(key: nil, value: nil)
12
+ end
13
+ end
14
+
15
+ attr_reader :id, :model_name, :score, :debug_info, :group
16
+
17
+ # TODO: model_name is specific for machinio
18
+ def initialize(id:, model_name: nil, score: nil, debug_info: nil, group: GroupInformation.empty)
19
+ @id = id
20
+ @model_name = model_name
21
+ @score = score
22
+ @debug_info = debug_info
23
+ @group = group
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,55 @@
1
+ module Solr
2
+ class DocumentCollection
3
+ include Enumerable
4
+ attr_reader :documents, :total_count
5
+
6
+ def self.from_ids(ids, model_name:)
7
+ documents = ids.map { |id| Solr::Document.new(id: id, model_name: model_name) }
8
+ new(documents: documents, total_count: documents.count)
9
+ end
10
+
11
+ def self.empty
12
+ new(documents: [], total_count: 0)
13
+ end
14
+
15
+ def initialize(documents:, total_count:)
16
+ @documents = documents
17
+ @total_count = total_count
18
+ end
19
+
20
+ def each(&b)
21
+ return enum_for(:each) unless block_given?
22
+ documents.each(&b)
23
+ end
24
+
25
+ def first(n)
26
+ new_documents = documents.first(n)
27
+ self.class.new(documents: new_documents, total_count: new_documents.count)
28
+ end
29
+
30
+ def slice(range)
31
+ new_documents = documents[range]
32
+ if new_documents
33
+ self.class.new(documents: new_documents, total_count: new_documents.count)
34
+ else
35
+ self.class.empty
36
+ end
37
+ end
38
+
39
+ def +(other)
40
+ self.class.new(
41
+ documents: documents + other.documents,
42
+ total_count: total_count + other.total_count
43
+ )
44
+ end
45
+
46
+ def unshift(document)
47
+ @documents.unshift(document)
48
+ @total_count += 1
49
+ end
50
+
51
+ def find(id)
52
+ documents.find { |doc| doc.id == id }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,9 @@
1
+ module Errors
2
+ class AmbiguousCoreError < StandardError
3
+ ERROR_MESSAGE = 'Multiple cores defined: default core can\'t be found'.freeze
4
+
5
+ def initialize
6
+ super(ERROR_MESSAGE)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ module Errors
2
+ class SolrQueryError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,16 @@
1
+ module Errors
2
+ class SolrUrlNotDefinedError < StandardError
3
+ SOLR_URL_NOT_DEFINED_MESSAGE = '
4
+ Solrb gem requires you to set the URL of your Solr instance
5
+ either through SOLR_URL environmental variable or explicitly inside the configure block:
6
+
7
+ Solr.configure do |config|
8
+ config.url = "http://localhost:8983/solr/core"
9
+ end
10
+ '.freeze
11
+
12
+ def initialize
13
+ super(SOLR_URL_NOT_DEFINED_MESSAGE)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ module Solr
2
+ class GroupedDocumentCollection < DocumentCollection
3
+ attr_reader :group_counts
4
+
5
+ def self.empty
6
+ new(documents: [], total_count: 0, group_counts: {})
7
+ end
8
+
9
+ def initialize(documents:, total_count:, group_counts:)
10
+ super(documents: documents, total_count: total_count)
11
+ @group_counts = group_counts
12
+ end
13
+
14
+ def first(n)
15
+ new_documents = documents.first(n)
16
+ self.class.new(documents: new_documents,
17
+ total_count: new_documents.count, group_counts: group_counts)
18
+ end
19
+
20
+ def slice(range)
21
+ new_documents = documents[range]
22
+ if new_documents
23
+ self.class.new(documents: new_documents, total_count: new_documents.count, group_counts: group_counts)
24
+ else
25
+ self.class.empty
26
+ end
27
+ end
28
+
29
+ def +(other)
30
+ other_group_counts = other.is_a?(Solr::GroupedDocumentCollection) ? other.group_counts : {}
31
+ self.class.new(
32
+ documents: documents + other.documents,
33
+ total_count: total_count + other.total_count,
34
+ group_counts: group_counts.merge(other_group_counts)
35
+ )
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,25 @@
1
+ module Solr
2
+ module Indexing
3
+ class Document
4
+ include Solr::Support::SchemaHelper
5
+ attr_reader :fields
6
+
7
+ def initialize(fields = {})
8
+ @fields = fields
9
+ end
10
+
11
+ def add_field(name, value)
12
+ @fields[name] = value
13
+ end
14
+
15
+ # TODO: refactor & optimize this
16
+ def to_json(_json_context)
17
+ solr_fields = fields.map do |k, v|
18
+ solr_field_name = solarize_field(k)
19
+ [solr_field_name, v]
20
+ end.to_h
21
+ JSON.generate(solr_fields)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module Solr
2
+ module Indexing
3
+ class Request
4
+ include Solr::Support::ConnectionHelper
5
+
6
+ # TODO: potentially make handlers configurable and have them handle the path
7
+ PATH = '/update'.freeze
8
+
9
+ attr_reader :documents
10
+
11
+ def initialize(documents = [])
12
+ @documents = documents
13
+ end
14
+
15
+ def run(commit: false)
16
+ # need to think how to move out commit data from the connection, it doesn't belong there
17
+ raw_response = connection(PATH, commit: commit).post_as_json(documents)
18
+ Solr::Response.from_raw_response(raw_response)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,9 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ module BoostMagnitude
5
+ DEFAULT = 1
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class DictionaryBoostFunction
6
+ include Solr::Support::SchemaHelper
7
+ using Solr::Support::StringExtensions
8
+ attr_reader :field, :dictionary
9
+
10
+ def initialize(field:, dictionary:)
11
+ raise 'dictionary must be a non-empty Hash' if Hash(dictionary).empty?
12
+ @field = field
13
+ @dictionary = dictionary
14
+ end
15
+
16
+ # example: given a hash (dictionary)
17
+ # {3025 => 2.0, 3024 => 1.5, 3023 => 1.2}
18
+ # and a field of category_id
19
+ # the resulting boosting function will be:
20
+ # if(eq(category_id_it, 3025), 2.0, if(eq(category_id_it, 3024), 1.5, if(eq(category_id_it, 3023), 1.2, 1)))
21
+ # note that I added spaces for readability, real Solr query functions must always be w/out spaces
22
+ def to_solr_s
23
+ sf = solarize_field(field)
24
+ dictionary.to_a.reverse.reduce(1) do |acc, (field_value, boost)|
25
+ if field_value.is_a?(String) || field_value.is_a?(Symbol)
26
+ "if(termfreq(#{sf},\"#{field_value.to_s.solr_escape}\"),#{boost},#{acc})"
27
+ else
28
+ "if(eq(#{sf},#{field_value}),#{boost},#{acc})"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class ExistsBoostFunction
6
+ include Solr::Support::SchemaHelper
7
+
8
+ attr_reader :field, :boost_magnitude
9
+
10
+ def initialize(field:, boost_magnitude:)
11
+ @field = field
12
+ @boost_magnitude = boost_magnitude
13
+ freeze
14
+ end
15
+
16
+ def to_solr_s
17
+ "if(exists(#{solr_field}),#{boost_magnitude},1)"
18
+ end
19
+
20
+ def solr_field
21
+ solarize_field(field)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class FieldValueLessThanBoostFunction
6
+ include Solr::Support::SchemaHelper
7
+
8
+ attr_reader :field, :max, :boost_magnitude
9
+
10
+ def initialize(field:, max:, boost_magnitude:)
11
+ @field = field
12
+ @max = max
13
+ @boost_magnitude = boost_magnitude
14
+ freeze
15
+ end
16
+
17
+ def to_solr_s
18
+ solr_field = solarize_field(field)
19
+ "if(sub(#{max},max(#{solr_field},#{max})),1,#{boost_magnitude})"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class FieldValueMatchBoostFunction
6
+ include Solr::Support::SchemaHelper
7
+
8
+ attr_reader :field, :value, :boost_magnitude
9
+
10
+ def initialize(field:, value:, boost_magnitude:)
11
+ @field = field
12
+ @value = value
13
+ @boost_magnitude = boost_magnitude
14
+ freeze
15
+ end
16
+
17
+ def solr_field
18
+ solarize_field(field)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ # Spatial search:
2
+ # https://cwiki.apache.org/confluence/display/solr/Spatial+Search
3
+
4
+ module Solr
5
+ module Query
6
+ class Request
7
+ class Boosting
8
+ class GeodistFunction
9
+ include Solr::Support::SchemaHelper
10
+
11
+ attr_reader :field, :latitude, :longitude
12
+
13
+ def initialize(field:, latitude:, longitude:)
14
+ @field = field
15
+ @latitude = latitude
16
+ @longitude = longitude
17
+ freeze
18
+ end
19
+
20
+ def to_solr_s
21
+ # this constants are magical, but they influence the slope of geo proximity decay function
22
+ 'recip(geodist(),3,17000,3000)'
23
+ end
24
+
25
+ # TODO: Check this dead code and the initialize arguments
26
+ def latlng
27
+ "#{latitude},#{longitude}"
28
+ end
29
+
30
+ def sfield
31
+ solarize_field(field)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class LnFunctionBoost
6
+ include Solr::Support::SchemaHelper
7
+
8
+ attr_reader :field, :min, :boost_magnitude
9
+
10
+ def initialize(field:, min: 0.69, boost_magnitude: 1)
11
+ @field = field
12
+ @min = min
13
+ @boost_magnitude = boost_magnitude
14
+ freeze
15
+ end
16
+
17
+ def to_solr_s
18
+ "mul(if(gt(#{solr_field},1),ln(#{solr_field}),#{min}),#{boost_magnitude})"
19
+ end
20
+
21
+ def solr_field
22
+ solarize_field(field)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class NumericFieldValueMatchBoostFunction < FieldValueMatchBoostFunction
6
+ def to_solr_s
7
+ "if(sub(def(#{solr_field},-1),#{value}),1,#{boost_magnitude})"
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ # https://wiki.apache.org/solr/ExtendedDisMax#pf_.28Phrase_Fields.29
6
+ # solr in action chapter 16.3.5
7
+ # we only need to do the phrase proximity boosting if we have a phrase, i.e. more than 1 word
8
+ class PhraseProximityBoost
9
+ include Solr::Support::SchemaHelper
10
+
11
+ attr_reader :field, :boost_magnitude
12
+
13
+ def initialize(field:, boost_magnitude:)
14
+ @field = field
15
+ @boost_magnitude = boost_magnitude
16
+ freeze
17
+ end
18
+
19
+ def to_solr_s
20
+ solr_field = solarize_field(field)
21
+ "#{solr_field}^#{boost_magnitude}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class RankingFieldBoostFunction
6
+ include Solr::Support::SchemaHelper
7
+ attr_reader :field
8
+
9
+ def initialize(field:)
10
+ @field = field
11
+ end
12
+
13
+ def to_solr_s
14
+ solarize_field(field).to_s
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class RecentFieldValueBoostFunction
6
+ include Solr::Support::SchemaHelper
7
+
8
+ attr_reader :field, :boost_magnitude, :max_age_days
9
+
10
+ def initialize(field:, boost_magnitude:, max_age_days:)
11
+ @field = field
12
+ @boost_magnitude = boost_magnitude
13
+ @max_age_days = max_age_days
14
+ freeze
15
+ end
16
+
17
+ def to_solr_s
18
+ solr_field = solarize_field(field)
19
+ recip_max_age_days_ms = 1.0 / (max_age_days * 24 * 3600 * 1000)
20
+ "mul(#{boost_magnitude},recip(ms(NOW,#{solr_field}),#{recip_max_age_days_ms},0.5,0.1))"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ module Solr
2
+ module Query
3
+ class Request
4
+ class Boosting
5
+ class ScaleFunctionBoost
6
+ include Solr::Support::SchemaHelper
7
+
8
+ attr_reader :field, :min, :max
9
+
10
+ def initialize(field:, min:, max:)
11
+ @field = field
12
+ @min = min
13
+ @max = max
14
+ freeze
15
+ end
16
+
17
+ def to_solr_s
18
+ "scale(#{solr_field},#{min},#{max})"
19
+ end
20
+
21
+ def solr_field
22
+ solarize_field(field)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end