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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/lsolr.rb +213 -0
  3. metadata +45 -0
@@ -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
@@ -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: []