solrb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|