solr_lite 0.0.9 → 0.0.10
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/lib/facet_field.rb +23 -2
- data/lib/filter_query.rb +55 -12
- data/lib/response.rb +26 -8
- data/lib/search_params.rb +23 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 72f7691a991ab4b1e073a57a357586676ba2406b2d237bb0645daa4a3afb4a29
|
|
4
|
+
data.tar.gz: 262d3a594d470b3968a9197bf7e4f7d806c39930562f906f2e067c492041678e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3bc6667f32f3ca2bb0adf22c73e90ec99b37189236ba0c72156d361dcf96423208809907c121679de3e5042ead3a6280fe4956bcbef7644bf125aed376e49b29
|
|
7
|
+
data.tar.gz: '02904a6967e638370c1218fe4c2621c6e61e11a64169c55dd2ff8fb30c2443f440246382b19f22e594169b699da90954d6b234061547c33607be5ae72c63c4eb'
|
data/lib/facet_field.rb
CHANGED
|
@@ -2,30 +2,51 @@ module SolrLite
|
|
|
2
2
|
class FacetField
|
|
3
3
|
|
|
4
4
|
class FacetValue
|
|
5
|
-
attr_accessor :text, :count, :remove_url, :add_url
|
|
5
|
+
attr_accessor :text, :count, :remove_url, :add_url, :range_start, :range_end
|
|
6
6
|
def initialize(text = "", count = 0, remove_url = nil)
|
|
7
7
|
@text = text
|
|
8
8
|
@count = count
|
|
9
9
|
@remove_url = remove_url
|
|
10
10
|
@add_url = nil
|
|
11
|
+
@range_start = nil
|
|
12
|
+
@range_end = nil
|
|
11
13
|
end
|
|
12
14
|
end
|
|
13
15
|
|
|
14
|
-
attr_accessor :name, :title, :values
|
|
16
|
+
attr_accessor :name, :title, :values,
|
|
17
|
+
:range, :range_start, :range_end, :range_gap
|
|
18
|
+
|
|
15
19
|
def initialize(name, display_value)
|
|
16
20
|
@name = name # field name in Solr
|
|
17
21
|
@title = display_value
|
|
18
22
|
@values = []
|
|
23
|
+
@ranges = []
|
|
24
|
+
@range = false
|
|
25
|
+
@range_start = nil
|
|
26
|
+
@range_end = nil
|
|
27
|
+
@range_gap = nil
|
|
19
28
|
end
|
|
20
29
|
|
|
21
30
|
def to_qs(text)
|
|
22
31
|
"#{@name}|#{CGI.escape(text)}"
|
|
23
32
|
end
|
|
24
33
|
|
|
34
|
+
def to_qs_range(range_start, range_end)
|
|
35
|
+
"#{@name}^#{range_start},#{range_end}"
|
|
36
|
+
end
|
|
37
|
+
|
|
25
38
|
def add_value(text, count)
|
|
26
39
|
@values << FacetValue.new(text, count)
|
|
27
40
|
end
|
|
28
41
|
|
|
42
|
+
def add_range(range_start, range_end, count)
|
|
43
|
+
text = "#{range_start} - #{range_end}"
|
|
44
|
+
value = FacetValue.new(text, count)
|
|
45
|
+
value.range_start = range_start
|
|
46
|
+
value.range_end = range_end
|
|
47
|
+
@values << value
|
|
48
|
+
end
|
|
49
|
+
|
|
29
50
|
def value_count(text)
|
|
30
51
|
v = @values.find {|v| v.text == text}
|
|
31
52
|
return 0 if v == nil
|
data/lib/filter_query.rb
CHANGED
|
@@ -8,22 +8,19 @@ module SolrLite
|
|
|
8
8
|
attr_accessor :field, :value, :solr_value, :qs_value, :form_value
|
|
9
9
|
attr_accessor :title, :remove_url
|
|
10
10
|
|
|
11
|
-
def initialize(field, values)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
values.each do |v|
|
|
17
|
-
@qs_value += "|#{CGI.escape(v)}" # URL friendly (no : or quotes)
|
|
11
|
+
def initialize(field, values, is_range = false)
|
|
12
|
+
if is_range
|
|
13
|
+
init_from_range(field, values.first)
|
|
14
|
+
else
|
|
15
|
+
init_from_values(field, values)
|
|
18
16
|
end
|
|
19
|
-
@form_value = "#{field}|#{@value}" # HTML Form friendly (no encoding, the form auto-encodes on POST)
|
|
20
|
-
@title = field # default to field name
|
|
21
|
-
@remove_url = nil
|
|
22
17
|
end
|
|
23
18
|
|
|
24
19
|
# qs is assumed to be the value taken from the query string
|
|
25
20
|
# in the form `field|value` or `field|value1|valueN`.
|
|
26
21
|
#
|
|
22
|
+
# For range values the format is: `field^start,end`
|
|
23
|
+
#
|
|
27
24
|
# Sometimes(*) the string comes URL encoded, for example:
|
|
28
25
|
# `field|hello`
|
|
29
26
|
# `field|hello%20world`
|
|
@@ -32,9 +29,19 @@ module SolrLite
|
|
|
32
29
|
# (*) Values coming from HTML forms submitted via HTTP POST tend
|
|
33
30
|
# to be encoded slighly different than value submitted via
|
|
34
31
|
# HTTP GET requests.
|
|
32
|
+
#
|
|
33
|
+
# TODO: Should I remove support for multi-values
|
|
34
|
+
# (e.g. `field|value1|valueN`) since we are
|
|
35
|
+
# not using them? It will make the code here
|
|
36
|
+
# and in init_from_values() cleaner.
|
|
35
37
|
def self.from_query_string(qs)
|
|
38
|
+
is_range = false
|
|
36
39
|
tokens = CGI.unescape(qs).split("|")
|
|
37
|
-
|
|
40
|
+
if tokens.count < 2
|
|
41
|
+
tokens = CGI.unescape(qs).split("^")
|
|
42
|
+
return nil if tokens.count != 2
|
|
43
|
+
is_range = true
|
|
44
|
+
end
|
|
38
45
|
field = ""
|
|
39
46
|
values = []
|
|
40
47
|
tokens.each_with_index do |token, i|
|
|
@@ -44,7 +51,7 @@ module SolrLite
|
|
|
44
51
|
values << token
|
|
45
52
|
end
|
|
46
53
|
end
|
|
47
|
-
FilterQuery.new(field, values)
|
|
54
|
+
FilterQuery.new(field, values, is_range)
|
|
48
55
|
end
|
|
49
56
|
|
|
50
57
|
private
|
|
@@ -52,6 +59,8 @@ module SolrLite
|
|
|
52
59
|
# an array of values. Handles single and multi-value gracefully.
|
|
53
60
|
# For single-value it returns "(field:value)". For multi-value
|
|
54
61
|
# it returns "(field:value1) OR (field:value2)"
|
|
62
|
+
#
|
|
63
|
+
# TODO: Should multivalue use an AND instead of an OR?
|
|
55
64
|
def to_solr_fq_value(field, values)
|
|
56
65
|
solr_value = ""
|
|
57
66
|
values.each_with_index do |v, i|
|
|
@@ -64,5 +73,39 @@ module SolrLite
|
|
|
64
73
|
# Very important to escape the : otherwise URL.parse throws an error in Linux
|
|
65
74
|
CGI.escape(solr_value)
|
|
66
75
|
end
|
|
76
|
+
|
|
77
|
+
def to_solr_fq_value_range(field, range_start, range_end)
|
|
78
|
+
solr_value = '(' + field + ':[' + range_start + ' TO ' + range_end + '])'
|
|
79
|
+
# Very important to escape the : otherwise URL.parse throws an error in Linux
|
|
80
|
+
CGI.escape(solr_value)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# range_string is expected in the form "start,end"
|
|
84
|
+
def init_from_range(field, range_string)
|
|
85
|
+
@field = field
|
|
86
|
+
tokens = (range_string || "").split(",")
|
|
87
|
+
return nil if tokens.count != 2
|
|
88
|
+
range_start = tokens[0]
|
|
89
|
+
range_end = tokens[1]
|
|
90
|
+
@value = "#{range_start} - #{range_end}"
|
|
91
|
+
@solr_value = to_solr_fq_value_range(field, range_start, range_end)
|
|
92
|
+
@qs_value = "#{field}^#{range_string}"
|
|
93
|
+
@form_value = "#{field}^#{range_string}" # HTML Form friendly (no encoding, the form auto-encodes on POST)
|
|
94
|
+
@title = field # default to field name
|
|
95
|
+
@remove_url = nil
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def init_from_values(field, values)
|
|
99
|
+
@field = field
|
|
100
|
+
@value = values.join("|")
|
|
101
|
+
@solr_value = to_solr_fq_value(field, values)
|
|
102
|
+
@qs_value = "#{field}"
|
|
103
|
+
values.each do |v|
|
|
104
|
+
@qs_value += "|#{CGI.escape(v)}" # URL friendly (no : or quotes)
|
|
105
|
+
end
|
|
106
|
+
@form_value = "#{field}|#{@value}" # HTML Form friendly (no encoding, the form auto-encodes on POST)
|
|
107
|
+
@title = field # default to field name
|
|
108
|
+
@remove_url = nil
|
|
109
|
+
end
|
|
67
110
|
end # class
|
|
68
111
|
end # module
|
data/lib/response.rb
CHANGED
|
@@ -135,6 +135,7 @@ module SolrLite
|
|
|
135
135
|
|
|
136
136
|
def set_facet_values()
|
|
137
137
|
return if @solr_response["facet_counts"] == nil
|
|
138
|
+
solr_ranges = @solr_response["facet_counts"]["facet_ranges"] || {}
|
|
138
139
|
solr_facets = @solr_response["facet_counts"]["facet_fields"]
|
|
139
140
|
solr_facets.each do |solr_facet|
|
|
140
141
|
# solr_facet is an array with two elements, e.g.
|
|
@@ -144,16 +145,33 @@ module SolrLite
|
|
|
144
145
|
# the second element is an array with of value/count pairs (PEOPLE/32, ORG/4)
|
|
145
146
|
field_name = solr_facet[0]
|
|
146
147
|
facet_field = @params.facet_for_field(field_name)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
facet_field.
|
|
148
|
+
if facet_field.range
|
|
149
|
+
# Use the range values as the facet values.
|
|
150
|
+
#
|
|
151
|
+
# Notice that we are overloading the "values" field and therefore
|
|
152
|
+
# we lose (i.e. don't store) the actual facet values and their counts.
|
|
153
|
+
# We might want to rethink this and keep them both.
|
|
154
|
+
values = solr_ranges[facet_field.name]["counts"] || []
|
|
155
|
+
pairs_count = values.count/2
|
|
156
|
+
for pair in (1..pairs_count)
|
|
157
|
+
index = (pair-1) * 2
|
|
158
|
+
start_range = values[index].to_i
|
|
159
|
+
end_range = start_range + facet_field.range_gap - 1
|
|
160
|
+
count = values[index+1]
|
|
161
|
+
facet_field.add_range(start_range, end_range, count)
|
|
162
|
+
end
|
|
163
|
+
else
|
|
164
|
+
# Regular facet values
|
|
165
|
+
values = solr_facet[1]
|
|
166
|
+
pairs = values.count/2
|
|
167
|
+
for pair in (1..pairs)
|
|
168
|
+
index = (pair-1) * 2
|
|
169
|
+
text = values[index]
|
|
170
|
+
count = values[index+1]
|
|
171
|
+
facet_field.add_value(text, count)
|
|
172
|
+
end
|
|
154
173
|
end
|
|
155
174
|
end
|
|
156
|
-
# TODO: make sure we sort the FacetField.VALUES descending by count
|
|
157
175
|
end
|
|
158
176
|
|
|
159
177
|
def explainer()
|
data/lib/search_params.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
require "filter_query.rb"
|
|
2
3
|
require "facet_field.rb"
|
|
3
4
|
module SolrLite
|
|
@@ -158,21 +159,27 @@ module SolrLite
|
|
|
158
159
|
if @q != ""
|
|
159
160
|
qs += "&q=#{@q}"
|
|
160
161
|
end
|
|
162
|
+
|
|
163
|
+
# Filter query
|
|
161
164
|
@fq.each do |filter|
|
|
162
165
|
qs += "&fq=#{filter.solr_value}"
|
|
163
166
|
end
|
|
167
|
+
|
|
164
168
|
extra_fqs.each do |filter|
|
|
165
169
|
qs += "&fq=#{filter.solr_value}"
|
|
166
170
|
end
|
|
171
|
+
|
|
167
172
|
qs += "&rows=#{@page_size}"
|
|
168
173
|
qs += "&start=#{start_row()}"
|
|
169
174
|
if sort != ""
|
|
170
175
|
qs += "&sort=#{CGI.escape(@sort)}"
|
|
171
176
|
end
|
|
177
|
+
|
|
172
178
|
if @spellcheck
|
|
173
179
|
qs += "&spellcheck=on"
|
|
174
180
|
end
|
|
175
|
-
|
|
181
|
+
|
|
182
|
+
# Hit highlighting parameters
|
|
176
183
|
if @hl
|
|
177
184
|
qs += "&hl=true"
|
|
178
185
|
if @hl_fl != nil
|
|
@@ -182,16 +189,31 @@ module SolrLite
|
|
|
182
189
|
qs += "&hl.snippets=#{@hl_snippets}"
|
|
183
190
|
end
|
|
184
191
|
end
|
|
192
|
+
|
|
193
|
+
# Facets
|
|
185
194
|
if @facets.count > 0
|
|
186
195
|
qs += "&facet=on"
|
|
196
|
+
|
|
197
|
+
facet_ranges = @facets.select {|f| f.range == true }.map { |f| f.name }
|
|
198
|
+
facet_ranges.each do |field_name|
|
|
199
|
+
qs += "&facet.range=#{field_name}"
|
|
200
|
+
end
|
|
201
|
+
|
|
187
202
|
@facets.each do |f|
|
|
188
203
|
qs += "&facet.field=#{f.name}"
|
|
189
204
|
qs += "&f.#{f.name}.facet.mincount=1"
|
|
190
205
|
if @facet_limit != nil
|
|
191
206
|
qs += "&f.#{f.name}.facet.limit=#{@facet_limit}"
|
|
192
207
|
end
|
|
208
|
+
|
|
209
|
+
if f.range
|
|
210
|
+
qs += "&f.#{f.name}.facet.range.start=#{f.range_start}"
|
|
211
|
+
qs += "&f.#{f.name}.facet.range.end=#{f.range_end}"
|
|
212
|
+
qs += "&f.#{f.name}.facet.range.gap=#{f.range_gap}"
|
|
213
|
+
end
|
|
193
214
|
end
|
|
194
215
|
end
|
|
216
|
+
|
|
195
217
|
qs
|
|
196
218
|
end
|
|
197
219
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: solr_lite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hector Correa
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-01-
|
|
11
|
+
date: 2019-01-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A lightweight gem to connect to Solr and run queries. Requires no extra
|
|
14
14
|
dependencies.
|