lsolr 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|