lsolr 0.0.5 → 0.0.6
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 +5 -5
- data/lib/lsolr.rb +113 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5e5ca288040ec046e3df00c273dcd6c3ccc6bd31e6db172bb652ff377dddaaf4
|
4
|
+
data.tar.gz: d87df9ae56c1aa37c1b92e11c00c82b0a3afb44abdd7e918e48ab88cce69a7e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4da503d0ce9a2627630c35848d8e3dc0d1b5fdacbf60839d9973f82a7ac2cd79d29a73a57a4583ed2ebf3a98de9bd14a5488da55f77cc41f24010cb76c091e70
|
7
|
+
data.tar.gz: b0ad4353b239b32cfdaf828cfc201dae3b917f21f861c4c460787b575d0630ec60276ff9cd6a36d3daa8d9ee0cc24730df68206a11ae83ea8d283c83453de95c
|
data/lib/lsolr.rb
CHANGED
@@ -1,8 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'date'
|
4
|
+
|
3
5
|
# A query builder of Apache Solr standard Lucene type query for Ruby.
|
4
6
|
#
|
5
|
-
# @example How to use.
|
7
|
+
# @example How to use. Part 1:
|
8
|
+
# LSolr.build(term1: 'hoge', term2: true).to_s
|
9
|
+
# #=> 'term1:hoge AND term2:true'
|
10
|
+
#
|
11
|
+
# @example How to use. Part 2:
|
12
|
+
# params = {
|
13
|
+
# term01: 'hoge',
|
14
|
+
# term02: :fuga,
|
15
|
+
# term03: 14,
|
16
|
+
# term04: 7.3,
|
17
|
+
# term05: true,
|
18
|
+
# term06: false,
|
19
|
+
# term07: Date.new(7000, 7, 1),
|
20
|
+
# term08: DateTime.new(6000, 5, 31, 6, 31, 43),
|
21
|
+
# term09: Time.new(5000, 6, 30, 12, 59, 3),
|
22
|
+
# term10: LSolr.new(:term10).fuzzy_match('foo'),
|
23
|
+
# term11: [1, 2, 3],
|
24
|
+
# term12: 1..10,
|
25
|
+
# term13: 20...40,
|
26
|
+
# term14: Date.new(3000, 1, 1)..Date.new(4000, 12, 31),
|
27
|
+
# term15: (3.0..4.0).step(0.1)
|
28
|
+
# }
|
29
|
+
#
|
30
|
+
# LSolr.build(params).to_s
|
31
|
+
# #=> 'term01:hoge AND term02:fuga AND term03:14 AND term04:7.3 AND term05:true
|
32
|
+
# # AND term06:false AND term07:"7000-07-01T00:00:00Z" AND term08:"6000-05-31T06:31:43Z"
|
33
|
+
# # AND term09:"5000-06-30T12:59:03Z" AND term10:foo~2.0 AND (term11:1 OR term11:2 OR term11:3)
|
34
|
+
# # AND term12:[1 TO 10] AND term13:[20 TO 40} AND term14:[3000-01-01T00:00:00Z TO 4000-12-31T00:00:00Z]
|
35
|
+
# # AND term15:[3.0 TO 4.0]'
|
36
|
+
#
|
37
|
+
# @example How to use. Part 3:
|
6
38
|
# monoclinic = LSolr.new(:crystal_system).match(:monoclinic)
|
7
39
|
# cubic = LSolr.new(:crystal_system).match(:cubic)
|
8
40
|
# soft = LSolr.new(:mohs_scale).greater_than_or_equal_to('*').less_than(5.0)
|
@@ -27,7 +59,12 @@ class LSolr
|
|
27
59
|
WILD_CARD = '*'
|
28
60
|
PROXIMITY = '~'
|
29
61
|
BOOST = '^'
|
62
|
+
PHRASE_MATCH_DELIMITER = ' '
|
30
63
|
FUZZY_MATCH_DISTANCE_RANGE = (0.0..2.0).freeze
|
64
|
+
FORMAT_DATE_TIME = '%Y-%m-%dT%H:%M:%SZ'
|
65
|
+
FORMAT_MILLISECOND_FOR_DATE_TYPE = '%Q'
|
66
|
+
FORMAT_MILLISECOND_FOR_TIME_TYPE = '%L'
|
67
|
+
FORMAT_SECOND = '%s'
|
31
68
|
|
32
69
|
PARENTHESIS_LEFT = '('
|
33
70
|
PARENTHESIS_RIGHT = ')'
|
@@ -38,6 +75,49 @@ class LSolr
|
|
38
75
|
|
39
76
|
attr_accessor :prev, :operator, :left_parentheses, :right_parentheses
|
40
77
|
|
78
|
+
class << self
|
79
|
+
# Builds composite query and returns builder instance.
|
80
|
+
#
|
81
|
+
# @param params [Hash{Symbol => String, Integer, Float, true, false, Range, Date, Time}] query terms
|
82
|
+
#
|
83
|
+
# @return [LSolr] a instance
|
84
|
+
def build(params)
|
85
|
+
params.map { |f, v| build_query(f, v) }.reduce { |a, e| a.and(e) }
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def build_query(field, value) # rubocop:disable Metrics/CyclomaticComplexity
|
91
|
+
case value
|
92
|
+
when String, Symbol, Integer, Float, true, false then new(field).match(value)
|
93
|
+
when Date, Time then new(field).date_time_match(value)
|
94
|
+
when LSolr then value
|
95
|
+
when Array then build_array_query(field, value)
|
96
|
+
when Range then build_range_query(field, value)
|
97
|
+
when Enumerator then build_enumerator_query(field, value)
|
98
|
+
else raise ArgumentError, "Could not build solr query. field: #{field}, value: #{value.inspect}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def build_array_query(field, values)
|
103
|
+
values.map { |v| build_query(field, v) }.reduce { |a, e| a.or(e) }.wrap
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_range_query(field, value)
|
107
|
+
if value.exclude_end?
|
108
|
+
new(field).greater_than_or_equal_to(value.first).less_than(value.last)
|
109
|
+
else
|
110
|
+
new(field).greater_than_or_equal_to(value.first).less_than_or_equal_to(value.last)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def build_enumerator_query(field, values)
|
115
|
+
last = nil
|
116
|
+
values.each { |v| last = v }
|
117
|
+
new(field).greater_than_or_equal_to(values.first).less_than_or_equal_to(last)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
41
121
|
# Create a new query builder instance.
|
42
122
|
#
|
43
123
|
# @param field [String] a field name
|
@@ -125,6 +205,7 @@ class LSolr
|
|
125
205
|
# @return [LSolr] self instance
|
126
206
|
def match(value)
|
127
207
|
values = clean(value).split
|
208
|
+
|
128
209
|
if values.size > 1
|
129
210
|
phrase_match(values)
|
130
211
|
else
|
@@ -135,11 +216,19 @@ class LSolr
|
|
135
216
|
|
136
217
|
# Builds a normal query expression with dates and times.
|
137
218
|
#
|
138
|
-
# @
|
219
|
+
# @see https://lucene.apache.org/solr/guide/6_6/working-with-dates.html Working with Dates
|
220
|
+
#
|
221
|
+
# @param value [String, Date, Time] a filter value
|
139
222
|
#
|
140
223
|
# @return [LSolr] self instance
|
141
224
|
def date_time_match(value)
|
142
|
-
|
225
|
+
value = if value.is_a?(Date) || value.is_a?(Time)
|
226
|
+
format_date(value)
|
227
|
+
else
|
228
|
+
clean(value, symbols: RESERVED_SYMBOLS - %w[- : . / +])
|
229
|
+
end
|
230
|
+
|
231
|
+
@value = %("#{value}")
|
143
232
|
self
|
144
233
|
end
|
145
234
|
|
@@ -165,7 +254,7 @@ class LSolr
|
|
165
254
|
#
|
166
255
|
# @return [LSolr] self instance
|
167
256
|
def phrase_match(values, distance: 0)
|
168
|
-
value = values.map { |v| clean(v).split }.flatten.join(
|
257
|
+
value = values.map { |v| clean(v).split }.flatten.join(PHRASE_MATCH_DELIMITER)
|
169
258
|
proximity_match = distance > 0 ? "#{PROXIMITY}#{distance}" : ''
|
170
259
|
@value = %("#{value}"#{proximity_match})
|
171
260
|
self
|
@@ -189,10 +278,11 @@ class LSolr
|
|
189
278
|
#
|
190
279
|
# @see https://lucene.apache.org/solr/guide/7_1/the-standard-query-parser.html#range-searches Range Searches
|
191
280
|
#
|
192
|
-
# @param value [String, Integer] a filter value
|
281
|
+
# @param value [String, Integer, Date, Time] a filter value
|
193
282
|
#
|
194
283
|
# @return [LSolr] self instance
|
195
284
|
def greater_than(value)
|
285
|
+
value = format_date(value) if value.is_a?(Date) || value.is_a?(Time)
|
196
286
|
@range_first = "#{GREATER_THAN}#{value}"
|
197
287
|
self
|
198
288
|
end
|
@@ -201,10 +291,11 @@ class LSolr
|
|
201
291
|
#
|
202
292
|
# @see https://lucene.apache.org/solr/guide/7_1/the-standard-query-parser.html#range-searches Range Searches
|
203
293
|
#
|
204
|
-
# @param value [String, Integer] a filter value
|
294
|
+
# @param value [String, Integer, Date, Time] a filter value
|
205
295
|
#
|
206
296
|
# @return [LSolr] self instance
|
207
297
|
def less_than(value)
|
298
|
+
value = format_date(value) if value.is_a?(Date) || value.is_a?(Time)
|
208
299
|
@range_last = "#{value}#{LESS_THAN}"
|
209
300
|
self
|
210
301
|
end
|
@@ -213,10 +304,11 @@ class LSolr
|
|
213
304
|
#
|
214
305
|
# @see https://lucene.apache.org/solr/guide/7_1/the-standard-query-parser.html#range-searches Range Searches
|
215
306
|
#
|
216
|
-
# @param value [String, Integer] a filter value
|
307
|
+
# @param value [String, Integer, Date, Time] a filter value
|
217
308
|
#
|
218
309
|
# @return [LSolr] self instance
|
219
310
|
def greater_than_or_equal_to(value)
|
311
|
+
value = format_date(value) if value.is_a?(Date) || value.is_a?(Time)
|
220
312
|
@range_first = "#{GREATER_THAN_OR_EQUAL_TO}#{value}"
|
221
313
|
self
|
222
314
|
end
|
@@ -225,10 +317,11 @@ class LSolr
|
|
225
317
|
#
|
226
318
|
# @see https://lucene.apache.org/solr/guide/7_1/the-standard-query-parser.html#range-searches Range Searches
|
227
319
|
#
|
228
|
-
# @param value [String, Integer] a filter value
|
320
|
+
# @param value [String, Integer, Date, Time] a filter value
|
229
321
|
#
|
230
322
|
# @return [LSolr] self instance
|
231
323
|
def less_than_or_equal_to(value)
|
324
|
+
value = format_date(value) if value.is_a?(Date) || value.is_a?(Time)
|
232
325
|
@range_last = "#{value}#{LESS_THAN_OR_EQUAL_TO}"
|
233
326
|
self
|
234
327
|
end
|
@@ -287,4 +380,16 @@ class LSolr
|
|
287
380
|
while !element.prev.nil? && element.prev.present? do element = element.prev end
|
288
381
|
element
|
289
382
|
end
|
383
|
+
|
384
|
+
def format_date(date)
|
385
|
+
msec_str = case date
|
386
|
+
when Date then date.strftime(FORMAT_MILLISECOND_FOR_DATE_TYPE).gsub(date.strftime(FORMAT_SECOND), '')
|
387
|
+
when Time then date.strftime(FORMAT_MILLISECOND_FOR_TIME_TYPE)
|
388
|
+
else raise ArgumentError, "Unknown type #{date.inspect}"
|
389
|
+
end
|
390
|
+
|
391
|
+
return date.strftime(FORMAT_DATE_TIME) if msec_str == '000'
|
392
|
+
|
393
|
+
"#{date.strftime('%Y-%m-%dT%H:%M:%S')}.#{msec_str}Z"
|
394
|
+
end
|
290
395
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lsolr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taishi Kasuga
|
@@ -38,7 +38,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
38
38
|
version: '0'
|
39
39
|
requirements: []
|
40
40
|
rubyforge_project:
|
41
|
-
rubygems_version: 2.
|
41
|
+
rubygems_version: 2.7.3
|
42
42
|
signing_key:
|
43
43
|
specification_version: 4
|
44
44
|
summary: A query builder of Apache Solr for Ruby
|