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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +69 -0
- data/.circleci/run-with-local-config.sh +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +30 -0
- data/.ruby-version +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +83 -0
- data/LICENSE.txt +21 -0
- data/README.md +259 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/solr/commit/request.rb +15 -0
- data/lib/solr/configuration.rb +66 -0
- data/lib/solr/connection.rb +33 -0
- data/lib/solr/core_configuration/core_config.rb +44 -0
- data/lib/solr/core_configuration/core_config_builder.rb +51 -0
- data/lib/solr/core_configuration/dynamic_field.rb +17 -0
- data/lib/solr/core_configuration/field.rb +20 -0
- data/lib/solr/delete/request.rb +34 -0
- data/lib/solr/document.rb +26 -0
- data/lib/solr/document_collection.rb +55 -0
- data/lib/solr/errors/ambiguous_core_error.rb +9 -0
- data/lib/solr/errors/solr_query_error.rb +4 -0
- data/lib/solr/errors/solr_url_not_defined_error.rb +16 -0
- data/lib/solr/grouped_document_collection.rb +38 -0
- data/lib/solr/indexing/document.rb +25 -0
- data/lib/solr/indexing/request.rb +22 -0
- data/lib/solr/query/request/boost_magnitude.rb +9 -0
- data/lib/solr/query/request/boosting/dictionary_boost_function.rb +36 -0
- data/lib/solr/query/request/boosting/exists_boost_function.rb +27 -0
- data/lib/solr/query/request/boosting/field_value_less_than_boost_function.rb +25 -0
- data/lib/solr/query/request/boosting/field_value_match_boost_function.rb +24 -0
- data/lib/solr/query/request/boosting/geodist_function.rb +37 -0
- data/lib/solr/query/request/boosting/ln_function_boost.rb +28 -0
- data/lib/solr/query/request/boosting/numeric_field_value_match_boost_function.rb +13 -0
- data/lib/solr/query/request/boosting/phrase_proximity_boost.rb +27 -0
- data/lib/solr/query/request/boosting/ranking_field_boost_function.rb +20 -0
- data/lib/solr/query/request/boosting/recent_field_value_boost_function.rb +26 -0
- data/lib/solr/query/request/boosting/scale_function_boost.rb +28 -0
- data/lib/solr/query/request/boosting/textual_field_value_match_boost_function.rb +13 -0
- data/lib/solr/query/request/boosting.rb +46 -0
- data/lib/solr/query/request/edismax_adapter.rb +163 -0
- data/lib/solr/query/request/facet.rb +68 -0
- data/lib/solr/query/request/field_with_boost.rb +18 -0
- data/lib/solr/query/request/filter.rb +73 -0
- data/lib/solr/query/request/geo_filter.rb +26 -0
- data/lib/solr/query/request/grouping.rb +37 -0
- data/lib/solr/query/request/or_filter.rb +16 -0
- data/lib/solr/query/request/runner.rb +46 -0
- data/lib/solr/query/request/sorting/field.rb +16 -0
- data/lib/solr/query/request/sorting.rb +34 -0
- data/lib/solr/query/request/spellcheck.rb +74 -0
- data/lib/solr/query/request.rb +49 -0
- data/lib/solr/query/response/facet_value.rb +16 -0
- data/lib/solr/query/response/field_facets.rb +25 -0
- data/lib/solr/query/response/parser.rb +154 -0
- data/lib/solr/query/response/spellcheck.rb +42 -0
- data/lib/solr/query/response.rb +48 -0
- data/lib/solr/response/header.rb +25 -0
- data/lib/solr/response/http_status.rb +27 -0
- data/lib/solr/response/parser.rb +47 -0
- data/lib/solr/response/solr_error.rb +31 -0
- data/lib/solr/response.rb +52 -0
- data/lib/solr/support/connection_helper.rb +12 -0
- data/lib/solr/support/hash_extensions.rb +29 -0
- data/lib/solr/support/schema_helper.rb +11 -0
- data/lib/solr/support/string_extensions.rb +12 -0
- data/lib/solr/support/url_helper.rb +12 -0
- data/lib/solr/support.rb +5 -0
- data/lib/solr/testing.rb +19 -0
- data/lib/solr/version.rb +3 -0
- data/lib/solr.rb +65 -0
- data/solrb.gemspec +36 -0
- metadata +261 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'solr/query/request/boosting/scale_function_boost'
|
2
|
+
require 'solr/query/request/boosting/geodist_function'
|
3
|
+
require 'solr/query/request/boosting/recent_field_value_boost_function'
|
4
|
+
require 'solr/query/request/boosting/ranking_field_boost_function'
|
5
|
+
require 'solr/query/request/boosting/field_value_match_boost_function'
|
6
|
+
require 'solr/query/request/boosting/numeric_field_value_match_boost_function'
|
7
|
+
require 'solr/query/request/boosting/textual_field_value_match_boost_function'
|
8
|
+
require 'solr/query/request/boosting/dictionary_boost_function'
|
9
|
+
require 'solr/query/request/boosting/exists_boost_function'
|
10
|
+
require 'solr/query/request/boosting/field_value_less_than_boost_function'
|
11
|
+
require 'solr/query/request/boosting/ln_function_boost'
|
12
|
+
require 'solr/query/request/boosting/phrase_proximity_boost'
|
13
|
+
|
14
|
+
module Solr
|
15
|
+
module Query
|
16
|
+
class Request
|
17
|
+
class Boosting
|
18
|
+
class << self
|
19
|
+
def empty
|
20
|
+
@empty ||= new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :additive_boost_functions, :multiplicative_boost_functions, :phrase_boosts, :spatial_boost
|
25
|
+
|
26
|
+
def initialize(additive_boost_functions: [], multiplicative_boost_functions: [], phrase_boosts: [])
|
27
|
+
@additive_boost_functions = additive_boost_functions
|
28
|
+
@multiplicative_boost_functions = multiplicative_boost_functions
|
29
|
+
@phrase_boosts = phrase_boosts
|
30
|
+
@spatial_boost = find_spatial_boost
|
31
|
+
freeze
|
32
|
+
end
|
33
|
+
|
34
|
+
def empty?
|
35
|
+
[multiplicative_boost_functions, additive_boost_functions, phrase_boosts].all(&:empty?)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def find_spatial_boost
|
41
|
+
multiplicative_boost_functions.find { |mbf| mbf.is_a? ::Solr::Query::Request::Boosting::GeodistFunction }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class EdismaxAdapter
|
5
|
+
SOLR_INFINITY = '*'.freeze # for cases like [100000 TO *]
|
6
|
+
include Solr::Support::SchemaHelper
|
7
|
+
|
8
|
+
EDISMAX_QUERY_FIELDS = :qf
|
9
|
+
EDISMAX_FILTER_QUERY = :fq
|
10
|
+
EDISMAX_ADDITIVE_BOOST_FUNCTION = :bf
|
11
|
+
EDISMAX_MULTIPLICATIVE_BOOST_FUNCTION = :boost
|
12
|
+
EDISMAX_PHRASE_BOOST = :pf
|
13
|
+
EDISMAX_PHRASE_SLOP = :ps
|
14
|
+
RESPONSE_FIELDS = :fl
|
15
|
+
RERANK_QUERY = :rq
|
16
|
+
QUERY_OPERATOR = :'q.op'
|
17
|
+
|
18
|
+
attr_reader :request
|
19
|
+
|
20
|
+
def initialize(request)
|
21
|
+
@request = request
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_h
|
25
|
+
solr_params = { q: request.search_term, defType: :edismax }
|
26
|
+
solr_params = add_query_fields(solr_params)
|
27
|
+
solr_params = add_response_fields(solr_params)
|
28
|
+
solr_params = add_filters(solr_params)
|
29
|
+
solr_params = add_facets(solr_params)
|
30
|
+
solr_params = add_boosting(solr_params)
|
31
|
+
solr_params = add_grouping(solr_params)
|
32
|
+
solr_params = add_sorting(solr_params)
|
33
|
+
solr_params = add_debug(solr_params)
|
34
|
+
solr_params = add_spellcheck(solr_params)
|
35
|
+
solr_params = add_rerank_query(solr_params)
|
36
|
+
solr_params = add_phrase_slop(solr_params)
|
37
|
+
solr_params = add_query_operator(solr_params)
|
38
|
+
solr_params
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def add_query_fields(solr_params)
|
44
|
+
fields = request.fields.map(&:to_solr_s)
|
45
|
+
solr_params.merge(EDISMAX_QUERY_FIELDS => fields)
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_filters(solr_params)
|
49
|
+
filters = request.filters.map(&:to_solr_s)
|
50
|
+
solr_params.merge(EDISMAX_FILTER_QUERY => filters)
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_facets(solr_params)
|
54
|
+
return solr_params if Array(request.facets).empty?
|
55
|
+
|
56
|
+
solr_params['json.facet'] = request.facets.map(&:to_solr_h).reduce(&:merge).to_json
|
57
|
+
|
58
|
+
solr_params
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_boosting(solr_params)
|
62
|
+
return solr_params unless request.boosting
|
63
|
+
solr_params = add_additive_boost_functions(solr_params)
|
64
|
+
solr_params = add_multiplicative_boost_functions(solr_params)
|
65
|
+
add_phrase_boosts(solr_params)
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_additive_boost_functions(solr_params)
|
69
|
+
additive_boosts = request.boosting.additive_boost_functions.map(&:to_solr_s)
|
70
|
+
if additive_boosts.any?
|
71
|
+
solr_params.merge(EDISMAX_ADDITIVE_BOOST_FUNCTION => additive_boosts)
|
72
|
+
else
|
73
|
+
solr_params
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_multiplicative_boost_functions(solr_params)
|
78
|
+
multiplicative_boosts = request.boosting.multiplicative_boost_functions.map(&:to_solr_s)
|
79
|
+
if multiplicative_boosts.any?
|
80
|
+
solr_params = solr_params.merge(EDISMAX_MULTIPLICATIVE_BOOST_FUNCTION => multiplicative_boosts)
|
81
|
+
# https://stackoverflow.com/questions/47025453/
|
82
|
+
maybe_add_spatial_fields(solr_params, request.boosting.spatial_boost)
|
83
|
+
else
|
84
|
+
solr_params
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_phrase_boosts(solr_params)
|
89
|
+
solr_phrase_boosts = request.boosting.phrase_boosts.map(&:to_solr_s)
|
90
|
+
if solr_phrase_boosts.any?
|
91
|
+
solr_params.merge(EDISMAX_PHRASE_BOOST => solr_phrase_boosts)
|
92
|
+
else
|
93
|
+
solr_params
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def maybe_add_spatial_fields(solr_params, geodist_function)
|
98
|
+
if geodist_function
|
99
|
+
solr_params.merge(pt: geodist_function.latlng, sfield: geodist_function.sfield)
|
100
|
+
else
|
101
|
+
solr_params
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_grouping(solr_params)
|
106
|
+
return solr_params if request.grouping.empty?
|
107
|
+
group_info = {
|
108
|
+
'group' => true,
|
109
|
+
'group.format' => 'grouped',
|
110
|
+
'group.limit' => request.grouping.limit,
|
111
|
+
'group.field' => solarize_field(request.grouping.field)
|
112
|
+
}
|
113
|
+
solr_params.merge(group_info)
|
114
|
+
end
|
115
|
+
|
116
|
+
def add_sorting(solr_params)
|
117
|
+
return solr_params if request.sorting.empty?
|
118
|
+
# sorting nulls last, not-nulls first
|
119
|
+
solr_sorting = request.sorting.fields.map do |sort_field|
|
120
|
+
solr_field = solarize_field(sort_field.name)
|
121
|
+
"exists(#{solr_field}) desc, #{solr_field} #{sort_field.direction}"
|
122
|
+
end
|
123
|
+
solr_params.merge(sort: solr_sorting)
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_response_fields(solr_params)
|
127
|
+
response_fields = 'id'
|
128
|
+
response_fields += ',score' if debug_mode?
|
129
|
+
response_fields += request.response_fields if request.response_fields
|
130
|
+
solr_params.merge(RESPONSE_FIELDS => response_fields)
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_debug(solr_params)
|
134
|
+
solr_params.merge(debug: debug_mode?)
|
135
|
+
end
|
136
|
+
|
137
|
+
def debug_mode?
|
138
|
+
request.debug_mode
|
139
|
+
end
|
140
|
+
|
141
|
+
def add_spellcheck(solr_params)
|
142
|
+
solr_params.merge(request.spellcheck.to_h)
|
143
|
+
end
|
144
|
+
|
145
|
+
def add_rerank_query(solr_params)
|
146
|
+
return solr_params unless request.limit_docs_by_field
|
147
|
+
rerank_query = request.limit_docs_by_field.to_solr_s
|
148
|
+
solr_params.merge(RERANK_QUERY => rerank_query)
|
149
|
+
end
|
150
|
+
|
151
|
+
def add_phrase_slop(solr_params)
|
152
|
+
return solr_params unless request.phrase_slop
|
153
|
+
solr_params.merge(EDISMAX_PHRASE_SLOP => request.phrase_slop)
|
154
|
+
end
|
155
|
+
|
156
|
+
def add_query_operator(solr_params)
|
157
|
+
return solr_params unless request.query_operator
|
158
|
+
solr_params.merge(QUERY_OPERATOR => request.query_operator)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class Facet
|
5
|
+
include Solr::Support::SchemaHelper
|
6
|
+
|
7
|
+
TERMS_TYPE = :terms
|
8
|
+
QUERY_TYPE = :query
|
9
|
+
RANGE_TYPE = :range
|
10
|
+
|
11
|
+
attr_reader :field,
|
12
|
+
:type,
|
13
|
+
:name,
|
14
|
+
:value,
|
15
|
+
:limit,
|
16
|
+
:filters,
|
17
|
+
:subfacets,
|
18
|
+
:gap,
|
19
|
+
:lower_bound,
|
20
|
+
:upper_bound
|
21
|
+
|
22
|
+
def initialize(field:, type:, name: nil, value: nil, filters: [], subfacets: [], options: {})
|
23
|
+
if options[:limit].nil? && type == TERMS_TYPE
|
24
|
+
raise ArgumentError, "Need to specify :limit option value for 'terms' facet type"
|
25
|
+
end
|
26
|
+
|
27
|
+
if options.values_at(:gap, :lower_bound, :upper_bound).any?(&:nil?) && type == RANGE_TYPE
|
28
|
+
raise ArgumentError, "Need to specify :lower_bound, :upper_bound, :gap option values for 'range' facet type"
|
29
|
+
end
|
30
|
+
|
31
|
+
@field = field
|
32
|
+
@name = name || field
|
33
|
+
@type = type
|
34
|
+
@value = value
|
35
|
+
@filters = filters
|
36
|
+
@subfacets = subfacets
|
37
|
+
@limit = options[:limit].to_i
|
38
|
+
@gap = options[:gap]
|
39
|
+
@lower_bound = options[:lower_bound]
|
40
|
+
@upper_bound = options[:upper_bound]
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_solr_h
|
44
|
+
return { name.to_s => value } if type == QUERY_TYPE && value
|
45
|
+
|
46
|
+
default_solr_h
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def default_solr_h
|
52
|
+
{
|
53
|
+
"#{name}": {
|
54
|
+
type: type,
|
55
|
+
field: solarize_field(field),
|
56
|
+
limit: limit,
|
57
|
+
q: filters.any? ? filters.map(&:to_solr_s).join(' AND ') : nil,
|
58
|
+
facet: subfacets.map(&:to_solr_h).reduce(&:merge),
|
59
|
+
gap: gap,
|
60
|
+
start: lower_bound,
|
61
|
+
end: upper_bound
|
62
|
+
}.compact
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class FieldWithBoost
|
5
|
+
attr_reader :field, :boost_magnitude
|
6
|
+
|
7
|
+
def initialize(field:, boost_magnitude: Solr::Query::Request::BoostMagnitude::DEFAULT)
|
8
|
+
@field = field
|
9
|
+
@boost_magnitude = boost_magnitude
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_solr_s
|
13
|
+
"#{field}^#{boost_magnitude}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module Solr
|
4
|
+
module Query
|
5
|
+
class Request
|
6
|
+
class Filter
|
7
|
+
include Solr::Support::SchemaHelper
|
8
|
+
using Solr::Support::StringExtensions
|
9
|
+
|
10
|
+
EQUAL_TYPE = :equal
|
11
|
+
NOT_EQUAL_TYPE = :not_equal
|
12
|
+
attr_reader :type, :field, :value
|
13
|
+
|
14
|
+
def initialize(type:, field:, value:)
|
15
|
+
@type = type
|
16
|
+
@field = field
|
17
|
+
@value = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_solr_s
|
21
|
+
"#{solr_prefix}#{solr_field}:(#{solr_value})"
|
22
|
+
end
|
23
|
+
|
24
|
+
def solr_field
|
25
|
+
solarize_field(@field)
|
26
|
+
end
|
27
|
+
|
28
|
+
def solr_value
|
29
|
+
if value.is_a?(::Array)
|
30
|
+
value.map { |v| to_primitive_solr_value(v) }.join(' OR ')
|
31
|
+
elsif value.is_a?(::Range)
|
32
|
+
to_interval_solr_value(value)
|
33
|
+
else
|
34
|
+
to_primitive_solr_value(value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def solr_prefix
|
41
|
+
'-' if NOT_EQUAL_TYPE == @type
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_interval_solr_value(range)
|
45
|
+
solr_min = to_primitive_solr_value(range.min)
|
46
|
+
solr_max = if date_infinity?(range.max) || range.max.to_f.infinite?
|
47
|
+
'*'
|
48
|
+
else
|
49
|
+
to_primitive_solr_value(range.max)
|
50
|
+
end
|
51
|
+
"[#{solr_min} TO #{solr_max}]"
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_primitive_solr_value(value)
|
55
|
+
if date_or_time?(value)
|
56
|
+
value.strftime('%Y-%m-%dT%H:%M:%SZ')
|
57
|
+
else
|
58
|
+
%("#{value.to_s.solr_escape}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def date_infinity?(value)
|
63
|
+
value.is_a?(DateTime::Infinity)
|
64
|
+
end
|
65
|
+
|
66
|
+
def date_or_time?(value)
|
67
|
+
return false unless value
|
68
|
+
value.is_a?(::Date) || value.is_a?(::Time)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class GeoFilter
|
5
|
+
SPATIAL_RADIUS = 161 # roughly 100mi
|
6
|
+
|
7
|
+
include Solr::Support::SchemaHelper
|
8
|
+
|
9
|
+
attr_reader :field, :latitude, :longitude, :spatial_radius
|
10
|
+
|
11
|
+
def initialize(field:, latitude:, longitude:, spatial_radius: SPATIAL_RADIUS)
|
12
|
+
@field = field
|
13
|
+
@latitude = latitude
|
14
|
+
@longitude = longitude
|
15
|
+
@spatial_radius = spatial_radius
|
16
|
+
freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_solr_s
|
20
|
+
solr_field = solarize_field(@field)
|
21
|
+
"{!geofilt sfield=#{solr_field} pt=#{@latitude},#{@longitude} d=#{spatial_radius}}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class Grouping
|
5
|
+
class None
|
6
|
+
def initialize
|
7
|
+
freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
def empty?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def inspect
|
15
|
+
'No Grouping'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :field, :limit
|
20
|
+
|
21
|
+
def self.none
|
22
|
+
None.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(field:, limit:)
|
26
|
+
@field = field
|
27
|
+
@limit = limit
|
28
|
+
freeze
|
29
|
+
end
|
30
|
+
|
31
|
+
def empty?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class OrFilter
|
5
|
+
def initialize(*filters)
|
6
|
+
@filters = filters
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_solr_s
|
10
|
+
subexpressions = @filters.map { |f| "#{f.solr_field}:(#{f.solr_value})" }
|
11
|
+
"(#{subexpressions.join(' OR ')})"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class Runner
|
5
|
+
PATH = '/select'.freeze
|
6
|
+
|
7
|
+
include Solr::Support::ConnectionHelper
|
8
|
+
|
9
|
+
attr_reader :page, :page_size, :solr_params
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def run(opts)
|
13
|
+
new(opts).run
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(page:, page_size:, solr_params: {})
|
18
|
+
@page = page
|
19
|
+
@page_size = page_size
|
20
|
+
@solr_params = solr_params
|
21
|
+
end
|
22
|
+
|
23
|
+
def run
|
24
|
+
raw_response = connection(PATH).post_as_json(request_params)
|
25
|
+
response = Solr::Response.from_raw_response(raw_response)
|
26
|
+
Solr.instrument(name: 'solrb.request_response_cycle',
|
27
|
+
data: { request: request_params, response: raw_response })
|
28
|
+
response
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def start
|
34
|
+
start_page = @page.to_i - 1
|
35
|
+
start_page = start_page < 1 ? 0 : start_page
|
36
|
+
start_page * page_size
|
37
|
+
end
|
38
|
+
|
39
|
+
def request_params
|
40
|
+
# https://lucene.apache.org/solr/guide/7_1/json-request-api.html#passing-parameters-via-json
|
41
|
+
@request_params ||= { params: solr_params.merge(wt: :json, rows: page_size.to_i, start: start) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class Sorting
|
5
|
+
ASC = :asc
|
6
|
+
DESC = :desc
|
7
|
+
class None
|
8
|
+
def initialize
|
9
|
+
freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
def empty?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :fields
|
18
|
+
|
19
|
+
def self.none
|
20
|
+
None.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(fields: [])
|
24
|
+
@fields = fields
|
25
|
+
freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
def empty?
|
29
|
+
fields.empty?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Solr
|
2
|
+
module Query
|
3
|
+
class Request
|
4
|
+
class Spellcheck
|
5
|
+
class Disabled
|
6
|
+
attr_reader :previous_search_term, :collated_search_term
|
7
|
+
|
8
|
+
def initialize(previous_search_term: nil, collated_search_term: nil)
|
9
|
+
@previous_search_term = previous_search_term
|
10
|
+
@collated_search_term = collated_search_term
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_h
|
14
|
+
{}
|
15
|
+
end
|
16
|
+
|
17
|
+
def collated?
|
18
|
+
collated_search_term.present?
|
19
|
+
end
|
20
|
+
|
21
|
+
def disabled?
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
'Disabled'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Default
|
31
|
+
def to_h
|
32
|
+
{
|
33
|
+
spellcheck: true,
|
34
|
+
'spellcheck.dictionary': 'spellcheck',
|
35
|
+
'spellcheck.count': 1,
|
36
|
+
'spellcheck.collate': true,
|
37
|
+
'spellcheck.maxCollations': 1,
|
38
|
+
'spellcheck.collateExtendedResults': true,
|
39
|
+
'spellcheck.maxCollationTries': 1,
|
40
|
+
'spellcheck.onlyMorePopular': true
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def previous_search_term; end
|
45
|
+
|
46
|
+
def collated_search_term; end
|
47
|
+
|
48
|
+
def collated?
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
def disabled?
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.collated(previous:, collated:)
|
58
|
+
Disabled.new(
|
59
|
+
previous_search_term: previous,
|
60
|
+
collated_search_term: collated
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.disabled
|
65
|
+
Disabled.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.default
|
69
|
+
Default.new
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'solr/query/request/facet'
|
2
|
+
require 'solr/query/request/filter'
|
3
|
+
require 'solr/query/request/boost_magnitude'
|
4
|
+
require 'solr/query/request/geo_filter'
|
5
|
+
require 'solr/query/request/sorting'
|
6
|
+
require 'solr/query/request/edismax_adapter'
|
7
|
+
require 'solr/query/request/grouping'
|
8
|
+
require 'solr/query/request/boosting'
|
9
|
+
require 'solr/query/request/spellcheck'
|
10
|
+
require 'solr/query/request/sorting/field'
|
11
|
+
require 'solr/query/request/field_with_boost'
|
12
|
+
require 'solr/query/request/or_filter'
|
13
|
+
require 'solr/query/request/runner'
|
14
|
+
require 'solr/query/response'
|
15
|
+
require 'solr/errors/solr_query_error'
|
16
|
+
|
17
|
+
module Solr
|
18
|
+
module Query
|
19
|
+
class Request
|
20
|
+
attr_reader :search_term
|
21
|
+
attr_accessor :filters, :fields, :facets, :boosting, :debug_mode, :spellcheck,
|
22
|
+
:limit_docs_by_field, :phrase_slop, :response_fields, :query_operator
|
23
|
+
attr_writer :grouping, :sorting
|
24
|
+
|
25
|
+
def initialize(search_term:, fields: [], filters: [])
|
26
|
+
@search_term = search_term
|
27
|
+
@fields = fields
|
28
|
+
@filters = filters
|
29
|
+
end
|
30
|
+
|
31
|
+
# Runs this Solr::Request against Solr and
|
32
|
+
# returns [Solr::Response]
|
33
|
+
def run(page: 1, page_size: 10)
|
34
|
+
solr_params = Solr::Query::Request::EdismaxAdapter.new(self).to_h
|
35
|
+
solr_response = Solr::Query::Request::Runner.run(page: page, page_size: page_size, solr_params: solr_params)
|
36
|
+
raise Errors::SolrQueryError, solr_response.error_message unless solr_response.ok?
|
37
|
+
Solr::Query::Response::Parser.new(request: self, solr_response: solr_response.body).to_response
|
38
|
+
end
|
39
|
+
|
40
|
+
def grouping
|
41
|
+
@grouping ||= Solr::Query::Request::Grouping.none
|
42
|
+
end
|
43
|
+
|
44
|
+
def sorting
|
45
|
+
@sorting ||= Solr::Query::Request::Sorting.none
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|