solrb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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