lsolr 0.0.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/lib/lsolr.rb +213 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d2af9d86ec14e9bf006d10b5af744e1c87a52f4d
|
4
|
+
data.tar.gz: 3891da477cf63a26da48b66f728687ffa99743a6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 46592b63cc533c78c7c66d23c1dc82b087e9ab0d14a44cc4b17947a454ee8ff6f5f0a722bd4bad4916a1478fa90a2b6f2f3db2d186c4ea173535402db0532578
|
7
|
+
data.tar.gz: 194b24916051035de0c74a92d7b19db852630416e865b821ca3f607a633652938b4a39e7d5abb752e2ae11ab40bdaa4470617046dfd973a91570cb1b111c6d04
|
data/lib/lsolr.rb
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @example How to use.
|
4
|
+
# monoclinic = LSolr.new(:crystal_system).match(:monoclinic)
|
5
|
+
# cubic = LSolr.new(:crystal_system).match(:cubic)
|
6
|
+
# soft = LSolr.new(:mohs_scale).greater_than_or_equal_to('*').less_than(5.0)
|
7
|
+
# hard = LSolr.new(:mohs_scale).greater_than_or_equal_to(5.0).less_than_or_equal_to(10.0)
|
8
|
+
#
|
9
|
+
# phosphophyllite = monoclinic.and(soft).wrap
|
10
|
+
# diamond = cubic.and(hard).wrap
|
11
|
+
#
|
12
|
+
# phosphophyllite.or(diamond).to_s
|
13
|
+
# #=> '(crystal_system:monoclinic AND mohs_scale:[* TO 5.0}) OR (crystal_system:cubic AND mohs_scale:[5.0 TO 10.0])'
|
14
|
+
class LSolr
|
15
|
+
NOT = 'NOT'
|
16
|
+
AND = 'AND'
|
17
|
+
OR = 'OR'
|
18
|
+
TO = 'TO'
|
19
|
+
|
20
|
+
GREATER_THAN = '{'
|
21
|
+
LESS_THAN = '}'
|
22
|
+
GREATER_THAN_OR_EQUAL_TO = '['
|
23
|
+
LESS_THAN_OR_EQUAL_TO = ']'
|
24
|
+
|
25
|
+
PROXIMITY = '~'
|
26
|
+
BOOST = '^'
|
27
|
+
FUZZY_MATCH_DISTANCE_RANGE = (0.0..1.0).freeze
|
28
|
+
|
29
|
+
PARENTHESIS_LEFT = '('
|
30
|
+
PARENTHESIS_RIGHT = ')'
|
31
|
+
|
32
|
+
RESERVED_SYMBOLS = %w(- + & | ! ( ) { } [ ] ^ " ~ * ? : \\\\ /).freeze
|
33
|
+
RESERVED_WORDS = /(AND|OR|NOT)/
|
34
|
+
REPLACEMENT_CHAR = ' '
|
35
|
+
|
36
|
+
attr_accessor :prev, :operator, :left_parentheses, :right_parentheses
|
37
|
+
|
38
|
+
# @param field [String] field name
|
39
|
+
# @return [LSolr] a instance
|
40
|
+
def initialize(field)
|
41
|
+
raise ArgumentError, 'Please specify a field name.' if field.nil? || field.empty?
|
42
|
+
|
43
|
+
@not = ''
|
44
|
+
@field = field
|
45
|
+
@value = ''
|
46
|
+
@range_first = ''
|
47
|
+
@range_last = ''
|
48
|
+
@boost = ''
|
49
|
+
@left_parentheses = []
|
50
|
+
@right_parentheses = []
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [String] a stringigied query
|
54
|
+
def to_s
|
55
|
+
@value = "#{@range_first} #{TO} #{@range_last}" if range_search?
|
56
|
+
raise 'Please specify a search condition.' if blank?
|
57
|
+
|
58
|
+
expr = "#{left_parentheses.join}#{@not}#{@field}:#{@value}#{right_parentheses.join}"
|
59
|
+
expr = "#{prev} #{operator} #{expr}" if prev&.present?
|
60
|
+
"#{expr}#{@boost}"
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [true] unless search condition specified
|
64
|
+
# @return [false] if search condition specified
|
65
|
+
def blank?
|
66
|
+
@value.empty? && (@range_first.empty? || @range_last.empty?)
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [true] if search condition specified
|
70
|
+
# @return [false] unless search condition specified
|
71
|
+
def present?
|
72
|
+
!blank?
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [LSolr] copied self instance
|
76
|
+
def wrap
|
77
|
+
this = dup
|
78
|
+
take_head(this).left_parentheses << PARENTHESIS_LEFT
|
79
|
+
this.right_parentheses << PARENTHESIS_RIGHT
|
80
|
+
this
|
81
|
+
end
|
82
|
+
|
83
|
+
# @return [LSolr] self instance
|
84
|
+
def not
|
85
|
+
@not = "#{NOT} "
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
# @param weight [Float] boost weight
|
90
|
+
# @return [LSolr] self instance
|
91
|
+
def boost(weight)
|
92
|
+
@boost = "#{BOOST}#{weight}"
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
# @param value [String, Integer, true, false] search word or filter value
|
97
|
+
# @return [LSolr] self instance
|
98
|
+
def match(value)
|
99
|
+
values = clean(value).split
|
100
|
+
if values.size > 1
|
101
|
+
phrase_match(values)
|
102
|
+
else
|
103
|
+
@value = values.join('')
|
104
|
+
self
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# @param value [String] filter value
|
109
|
+
# @return [LSolr] self instance
|
110
|
+
def date_time_match(value)
|
111
|
+
@value = clean(value, symbols: RESERVED_SYMBOLS - %w[- : . / +])
|
112
|
+
self
|
113
|
+
end
|
114
|
+
|
115
|
+
# @param value [String] search word
|
116
|
+
# @return [LSolr] self instance
|
117
|
+
def prefix_match(value)
|
118
|
+
@value = clean(value, symbols: RESERVED_SYMBOLS - %w[* ?])
|
119
|
+
self
|
120
|
+
end
|
121
|
+
|
122
|
+
# @param values [Array<String>] search word
|
123
|
+
# @param distance [Integer] proximity distance
|
124
|
+
# @return [LSolr] self instance
|
125
|
+
def phrase_match(values, distance: 0)
|
126
|
+
value = values.map { |v| clean(v) }.join(REPLACEMENT_CHAR)
|
127
|
+
proximity_match = distance.positive? ? "#{PROXIMITY}#{distance}" : ''
|
128
|
+
@value = %("#{value}"#{proximity_match})
|
129
|
+
self
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param value [String] search word
|
133
|
+
# @param distance [Float] proximity distance
|
134
|
+
# @return [LSolr] self instance
|
135
|
+
def fuzzy_match(value, distance: 0.0)
|
136
|
+
raise RangeError, "Out of #{FUZZY_MATCH_DISTANCE_RANGE}. #{distance} given." unless (FUZZY_MATCH_DISTANCE_RANGE).member?(distance)
|
137
|
+
@value = "#{clean(value)}#{PROXIMITY}#{distance}"
|
138
|
+
self
|
139
|
+
end
|
140
|
+
|
141
|
+
# @param value [String, Integer] filter value
|
142
|
+
# @return [LSolr] self instance
|
143
|
+
def greater_than(value)
|
144
|
+
@range_first = "#{GREATER_THAN}#{value}"
|
145
|
+
self
|
146
|
+
end
|
147
|
+
|
148
|
+
# @param value [String, Integer] filter value
|
149
|
+
# @return [LSolr] self instance
|
150
|
+
def less_than(value)
|
151
|
+
@range_last = "#{value}#{LESS_THAN}"
|
152
|
+
self
|
153
|
+
end
|
154
|
+
|
155
|
+
# @param value [String, Integer] filter value
|
156
|
+
# @return [LSolr] self instance
|
157
|
+
def greater_than_or_equal_to(value)
|
158
|
+
@range_first = "#{GREATER_THAN_OR_EQUAL_TO}#{value}"
|
159
|
+
self
|
160
|
+
end
|
161
|
+
|
162
|
+
# @param value [String, Integer] filter value
|
163
|
+
# @return [LSolr] self instance
|
164
|
+
def less_than_or_equal_to(value)
|
165
|
+
@range_last = "#{value}#{LESS_THAN_OR_EQUAL_TO}"
|
166
|
+
self
|
167
|
+
end
|
168
|
+
|
169
|
+
# @param another [LSolr] another instance
|
170
|
+
# @return [LSolr] copied another instance
|
171
|
+
def and(another)
|
172
|
+
link(another, AND)
|
173
|
+
end
|
174
|
+
|
175
|
+
# @param another [LSolr] another instance
|
176
|
+
# @return [LSolr] copied another instance
|
177
|
+
def or(another)
|
178
|
+
link(another, OR)
|
179
|
+
end
|
180
|
+
|
181
|
+
private
|
182
|
+
|
183
|
+
def initialize_copy(obj)
|
184
|
+
obj.prev = obj.prev.dup if obj.prev&.present?
|
185
|
+
obj.left_parentheses = obj.left_parentheses.dup
|
186
|
+
obj.right_parentheses = obj.right_parentheses.dup
|
187
|
+
end
|
188
|
+
|
189
|
+
def range_search?
|
190
|
+
@value.empty? && !@range_first.empty? && !@range_last.empty?
|
191
|
+
end
|
192
|
+
|
193
|
+
def clean(value, symbols: RESERVED_SYMBOLS)
|
194
|
+
value.to_s
|
195
|
+
.tr(symbols.join(''), REPLACEMENT_CHAR)
|
196
|
+
.gsub(RESERVED_WORDS) { |match| "\\#{match}" }
|
197
|
+
end
|
198
|
+
|
199
|
+
def link(another, operator)
|
200
|
+
return self if another.nil? || another.blank?
|
201
|
+
|
202
|
+
another = another.dup
|
203
|
+
head = take_head(another)
|
204
|
+
head.prev = dup
|
205
|
+
head.operator = operator
|
206
|
+
another
|
207
|
+
end
|
208
|
+
|
209
|
+
def take_head(element)
|
210
|
+
while element.prev&.present? do element = element.prev end
|
211
|
+
element
|
212
|
+
end
|
213
|
+
end
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lsolr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Taishi Kasuga
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-08 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: LSolr is a query builder of Apache Solr standard Lucene type query for
|
14
|
+
Ruby.
|
15
|
+
email: supercaracal@yahoo.co.jp
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/lsolr.rb
|
21
|
+
homepage: https://github.com/supercaracal/lsolr
|
22
|
+
licenses:
|
23
|
+
- MIT
|
24
|
+
metadata: {}
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.2.2
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
requirements: []
|
40
|
+
rubyforge_project:
|
41
|
+
rubygems_version: 2.6.14
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: A query builder of Apache Solr for Ruby
|
45
|
+
test_files: []
|