simple_solr_client 0.2.0 → 0.2.1
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/CHANGES.md +3 -0
- data/README.md +0 -3
- data/lib/simple_solr_client.rb +12 -7
- data/lib/simple_solr_client/client.rb +1 -1
- data/lib/simple_solr_client/core.rb +2 -8
- data/lib/simple_solr_client/core/admin.rb +0 -1
- data/lib/simple_solr_client/core/core_data.rb +0 -4
- data/lib/simple_solr_client/version.rb +1 -1
- data/simple_solr_client.gemspec +6 -8
- data/solr_sample_core/conf/schema.xml +3 -1
- data/solr_sample_core/conf/solrconfig.xml +1163 -1493
- data/spec/client_basics_spec.rb +5 -5
- data/spec/core_basics_spec.rb +21 -0
- data/spec/minitest_helper.rb +6 -3
- metadata +11 -36
- data/lib/simple_solr_client/schema.rb +0 -217
- data/lib/simple_solr_client/schema/analysis.rb +0 -79
- data/lib/simple_solr_client/schema/copyfield.rb +0 -42
- data/lib/simple_solr_client/schema/dynamic_field.rb +0 -23
- data/lib/simple_solr_client/schema/field.rb +0 -46
- data/lib/simple_solr_client/schema/field_or_type.rb +0 -112
- data/lib/simple_solr_client/schema/field_type.rb +0 -47
- data/lib/simple_solr_client/schema/matcher.rb +0 -16
- data/spec/core_basics.rb +0 -21
- data/spec/schema_spec.rb +0 -113
data/spec/client_basics_spec.rb
CHANGED
@@ -6,20 +6,20 @@ describe SimpleSolrClient::Client do
|
|
6
6
|
@client = TestClient.instance.client
|
7
7
|
end
|
8
8
|
it "creates a new object" do
|
9
|
-
@client.base_url.must_equal '
|
9
|
+
@client.base_url.must_equal ENV['TEST_SOLR_URL']
|
10
10
|
end
|
11
11
|
|
12
12
|
it "strips off a trailing slash for base_url" do
|
13
|
-
c = SimpleSolrClient::Client.new('
|
14
|
-
c.base_url.must_equal '
|
13
|
+
c = SimpleSolrClient::Client.new( ENV['TEST_SOLR_URL'])
|
14
|
+
c.base_url.must_equal ENV['TEST_SOLR_URL']
|
15
15
|
end
|
16
16
|
|
17
17
|
it "constructs a url with no args" do
|
18
|
-
@client.url.must_equal '
|
18
|
+
@client.url.must_equal ENV['TEST_SOLR_URL']
|
19
19
|
end
|
20
20
|
|
21
21
|
it "constructs a URL with args" do
|
22
|
-
@client.url('admin', 'ping').must_equal '
|
22
|
+
@client.url('admin', 'ping').must_equal "#{ENV['TEST_SOLR_URL']}/admin/ping"
|
23
23
|
end
|
24
24
|
|
25
25
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
|
3
|
+
describe SimpleSolrClient::Core do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@core = TempCore.instance.core('core_basics')
|
7
|
+
end
|
8
|
+
it "creates a new object" do
|
9
|
+
@core.base_url.must_equal ENV['TEST_SOLR_URL']
|
10
|
+
end
|
11
|
+
|
12
|
+
it "constructs a url with no args" do
|
13
|
+
@core.url.must_equal "#{ENV['TEST_SOLR_URL']}/#{@core.name}"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "constructs a URL with args" do
|
17
|
+
@core.url('admin', 'ping').must_equal "#{ENV['TEST_SOLR_URL']}/#{@core.name}/admin/ping"
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
end
|
data/spec/minitest_helper.rb
CHANGED
@@ -1,21 +1,24 @@
|
|
1
1
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
2
|
require 'simple_solr_client'
|
3
|
+
|
4
|
+
|
3
5
|
require 'minitest/spec'
|
4
6
|
require 'minitest/autorun'
|
5
7
|
require "minitest/reporters"
|
8
|
+
|
6
9
|
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
7
10
|
|
8
11
|
require 'singleton'
|
9
12
|
|
10
13
|
ENV['TEST_SOLR_URL'] ||= 'http://localhost:8983/solr'
|
11
|
-
ENV['TEST_SOLR_CORE_NAME'] ||= 'core1'
|
14
|
+
#ENV['TEST_SOLR_CORE_NAME'] ||= 'core1'
|
12
15
|
|
13
16
|
class TestClient
|
14
17
|
include Singleton
|
15
|
-
attr_reader :client
|
18
|
+
attr_reader :client #, :core
|
16
19
|
def initialize
|
17
20
|
@client = SimpleSolrClient::Client.new ENV['TEST_SOLR_URL']
|
18
|
-
@core = @client.core ENV['TEST_SOLR_CORE_NAME'] || 'simple_solr_test'
|
21
|
+
# @core = @client.core ENV['TEST_SOLR_CORE_NAME'] || 'simple_solr_test'
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_solr_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bill Dueber
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpclient
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: pry
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
@@ -42,32 +42,18 @@ dependencies:
|
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.7'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.7'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '10.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '10.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: minitest
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - ">="
|
@@ -81,7 +67,7 @@ dependencies:
|
|
81
67
|
- !ruby/object:Gem::Version
|
82
68
|
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name: minitest
|
70
|
+
name: minitest
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - ">="
|
@@ -95,13 +81,13 @@ dependencies:
|
|
95
81
|
- !ruby/object:Gem::Version
|
96
82
|
version: '0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
84
|
+
name: minitest-reporters
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
87
|
- - ">="
|
102
88
|
- !ruby/object:Gem::Version
|
103
89
|
version: '0'
|
104
|
-
type: :
|
90
|
+
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
@@ -134,14 +120,6 @@ files:
|
|
134
120
|
- lib/simple_solr_client/response/document.rb
|
135
121
|
- lib/simple_solr_client/response/generic_response.rb
|
136
122
|
- lib/simple_solr_client/response/query_response.rb
|
137
|
-
- lib/simple_solr_client/schema.rb
|
138
|
-
- lib/simple_solr_client/schema/analysis.rb
|
139
|
-
- lib/simple_solr_client/schema/copyfield.rb
|
140
|
-
- lib/simple_solr_client/schema/dynamic_field.rb
|
141
|
-
- lib/simple_solr_client/schema/field.rb
|
142
|
-
- lib/simple_solr_client/schema/field_or_type.rb
|
143
|
-
- lib/simple_solr_client/schema/field_type.rb
|
144
|
-
- lib/simple_solr_client/schema/matcher.rb
|
145
123
|
- lib/simple_solr_client/version.rb
|
146
124
|
- simple_solr_client.gemspec
|
147
125
|
- solr_sample_core/conf/_schema_analysis_stopwords_english.json
|
@@ -248,11 +226,10 @@ files:
|
|
248
226
|
- solr_sample_core/conf/xslt/updateXml.xsl
|
249
227
|
- spec/client_basics_spec.rb
|
250
228
|
- spec/connect_spec.rb
|
251
|
-
- spec/
|
229
|
+
- spec/core_basics_spec.rb
|
252
230
|
- spec/index_spec.rb
|
253
231
|
- spec/load_spec.rb
|
254
232
|
- spec/minitest_helper.rb
|
255
|
-
- spec/schema_spec.rb
|
256
233
|
homepage: https://github.com/billdueber/simple_solr
|
257
234
|
licenses:
|
258
235
|
- MIT
|
@@ -272,16 +249,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
272
249
|
- !ruby/object:Gem::Version
|
273
250
|
version: '0'
|
274
251
|
requirements: []
|
275
|
-
|
276
|
-
rubygems_version: 2.6.13
|
252
|
+
rubygems_version: 3.0.1
|
277
253
|
signing_key:
|
278
254
|
specification_version: 4
|
279
255
|
summary: Interact with a Solr API via JSON
|
280
256
|
test_files:
|
281
257
|
- spec/client_basics_spec.rb
|
282
258
|
- spec/connect_spec.rb
|
283
|
-
- spec/
|
259
|
+
- spec/core_basics_spec.rb
|
284
260
|
- spec/index_spec.rb
|
285
261
|
- spec/load_spec.rb
|
286
262
|
- spec/minitest_helper.rb
|
287
|
-
- spec/schema_spec.rb
|
@@ -1,217 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
|
-
require 'simple_solr_client/schema/matcher'
|
4
|
-
require 'simple_solr_client/schema/copyfield'
|
5
|
-
require 'simple_solr_client/schema/field'
|
6
|
-
require 'simple_solr_client/schema/dynamic_field'
|
7
|
-
require 'simple_solr_client/schema/field_type'
|
8
|
-
|
9
|
-
class SimpleSolrClient::Schema
|
10
|
-
# A simplistic representation of a schema
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(core)
|
14
|
-
@core = core
|
15
|
-
@fields = {}
|
16
|
-
@dynamic_fields = {}
|
17
|
-
@copy_fields = Hash.new { |h, k| h[k] = [] }
|
18
|
-
@field_types = {}
|
19
|
-
self.load
|
20
|
-
end
|
21
|
-
|
22
|
-
|
23
|
-
def fields
|
24
|
-
@fields.values.map { |x| x.resolve_type(self) }
|
25
|
-
end
|
26
|
-
|
27
|
-
def field(n)
|
28
|
-
@fields[n].resolve_type(self)
|
29
|
-
end
|
30
|
-
|
31
|
-
def dynamic_fields
|
32
|
-
@dynamic_fields.values.map { |x| x.resolve_type(self) }
|
33
|
-
end
|
34
|
-
|
35
|
-
def dynamic_field(n)
|
36
|
-
@dynamic_fields[n].resolve_type(self)
|
37
|
-
end
|
38
|
-
|
39
|
-
def copy_fields_for(n)
|
40
|
-
@copy_fields[n]
|
41
|
-
end
|
42
|
-
|
43
|
-
def copy_fields
|
44
|
-
@copy_fields.values.flatten
|
45
|
-
end
|
46
|
-
|
47
|
-
def add_field(f)
|
48
|
-
@fields[f.name] = f
|
49
|
-
field(f.name)
|
50
|
-
end
|
51
|
-
|
52
|
-
def drop_field(str)
|
53
|
-
@fields.delete(str)
|
54
|
-
self
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
def field_types
|
59
|
-
@field_types.values
|
60
|
-
end
|
61
|
-
|
62
|
-
def field_type(k)
|
63
|
-
@field_types[k]
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
# When we add dynamic fields, we need to keep them sorted by
|
68
|
-
# length of the key, since that's how they match
|
69
|
-
def add_dynamic_field(f)
|
70
|
-
raise "Dynamic field should be dynamic and have a '*' in it somewhere; '#{f.name}' does not" unless f.name =~ /\*/
|
71
|
-
@dynamic_fields[f.name] = f
|
72
|
-
|
73
|
-
@dynamic_fields = @dynamic_fields.sort { |a, b| b[0].size <=> a[0].size }.to_h
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
def drop_dynamic_field(str)
|
78
|
-
@dynamic_fields.delete(str)
|
79
|
-
self
|
80
|
-
end
|
81
|
-
|
82
|
-
def add_copy_field(f)
|
83
|
-
cf = @copy_fields[f.source]
|
84
|
-
cf << f
|
85
|
-
end
|
86
|
-
|
87
|
-
def drop_copy_field(str)
|
88
|
-
@copy_fields.delete(str)
|
89
|
-
self
|
90
|
-
end
|
91
|
-
|
92
|
-
def add_field_type(ft)
|
93
|
-
ft.core = @core
|
94
|
-
@field_types[ft.name] = ft
|
95
|
-
end
|
96
|
-
|
97
|
-
def drop_field_type(str)
|
98
|
-
@field_types.delete(str)
|
99
|
-
self
|
100
|
-
end
|
101
|
-
|
102
|
-
|
103
|
-
# For loading, we get the information about the fields via the API,
|
104
|
-
def load
|
105
|
-
load_explicit_fields
|
106
|
-
load_dynamic_fields
|
107
|
-
load_copy_fields
|
108
|
-
load_field_types
|
109
|
-
end
|
110
|
-
|
111
|
-
|
112
|
-
def load_explicit_fields
|
113
|
-
@fields = {}
|
114
|
-
@core.get('schema/fields')['fields'].each do |field_hash|
|
115
|
-
add_field(Field.new_from_solr_hash(field_hash))
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def load_dynamic_fields
|
120
|
-
@dynamic_fields = {}
|
121
|
-
@core.get('schema/dynamicfields')['dynamicFields'].each do |field_hash|
|
122
|
-
f = DynamicField.new_from_solr_hash(field_hash)
|
123
|
-
if @dynamic_fields[f.name]
|
124
|
-
raise "Dynamic field '#{f.name}' defined more than once"
|
125
|
-
end
|
126
|
-
add_dynamic_field(f)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def load_copy_fields
|
131
|
-
@copy_fields = Hash.new { |h, k| h[k] = [] }
|
132
|
-
@core.get('schema/copyfields')['copyFields'].each do |cfield_hash|
|
133
|
-
add_copy_field(CopyField.new(cfield_hash['source'], cfield_hash['dest']))
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def load_field_types
|
138
|
-
@field_types = {}
|
139
|
-
@core.get('schema/fieldtypes')['fieldTypes'].each do |fthash|
|
140
|
-
ft = FieldType.new_from_solr_hash(fthash)
|
141
|
-
add_field_type(ft)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def reload
|
146
|
-
@core.reload
|
147
|
-
end
|
148
|
-
|
149
|
-
|
150
|
-
# Figuring out which fields are actually produced can be hard:
|
151
|
-
# * If a non-dynamic field name matches, no dynamic_fields will match
|
152
|
-
# * The result of a copyField may match another dynamicField, but the
|
153
|
-
# result of *that* will not match more copyFields
|
154
|
-
# * dynamicFields are matched longest to shortest
|
155
|
-
#
|
156
|
-
# Suppose I have the following:
|
157
|
-
# dynamic *_ts => string
|
158
|
-
# dynamic *_t => string
|
159
|
-
# dynamic *_s => string
|
160
|
-
# dynamic *_ddd => string
|
161
|
-
#
|
162
|
-
# copy *_ts => *_t
|
163
|
-
# copy *_ts => *_s
|
164
|
-
# copy *_s => *_ddd
|
165
|
-
#
|
166
|
-
# You might expect:
|
167
|
-
# name_ts => string
|
168
|
-
# name_ts copied to name_t => string
|
169
|
-
# name_ts copied to name_s => string
|
170
|
-
# name_s copied to name_ddd => string
|
171
|
-
#
|
172
|
-
# ...giving us name_ts, name_t, name_s, and name_ddd
|
173
|
-
#
|
174
|
-
# What you'll find is that we don't get name_ddd, since
|
175
|
-
# name_s was generated by a wildcard-enabled copyField
|
176
|
-
# and that's where things stop.
|
177
|
-
#
|
178
|
-
# However, if you explicitly add a field called
|
179
|
-
# name_s, it *will* get copied to name_ddd.
|
180
|
-
#
|
181
|
-
# Yeah. It's confusing.
|
182
|
-
|
183
|
-
|
184
|
-
def first_matching_field(str)
|
185
|
-
f = fields.find { |x| x.matches str } or first_matching_dfield(str)
|
186
|
-
end
|
187
|
-
|
188
|
-
def first_matching_dfield(str)
|
189
|
-
df = dynamic_fields.find { |x| x.matches str }
|
190
|
-
if df
|
191
|
-
f = Field.new(df.to_h)
|
192
|
-
f[:name] = df.dynamic_name str
|
193
|
-
end
|
194
|
-
f
|
195
|
-
|
196
|
-
end
|
197
|
-
|
198
|
-
def resulting_fields(str)
|
199
|
-
rv = []
|
200
|
-
f = first_matching_field(str)
|
201
|
-
rv << f
|
202
|
-
copy_fields.each do |cf|
|
203
|
-
if cf.matches(f.name)
|
204
|
-
dname = cf.dynamic_name(f.name)
|
205
|
-
fmf = Field.new(first_matching_field(dname).to_h)
|
206
|
-
fmf[:name] = dname
|
207
|
-
rv << fmf
|
208
|
-
end
|
209
|
-
end
|
210
|
-
rv.uniq
|
211
|
-
end
|
212
|
-
|
213
|
-
end
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
@@ -1,79 +0,0 @@
|
|
1
|
-
# Figure out how the field type will parse out tokens
|
2
|
-
# and change them in the analysis chain. Just calls the
|
3
|
-
# provided solr analysis endpoints
|
4
|
-
#
|
5
|
-
# To be mixed into FieldType
|
6
|
-
|
7
|
-
class SimpleSolrClient::Schema
|
8
|
-
|
9
|
-
class InvalidTokenError < RuntimeError
|
10
|
-
attr_accessor :resp
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(msg, resp)
|
14
|
-
super(msg)
|
15
|
-
@resp = resp
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
module Analysis
|
20
|
-
|
21
|
-
#https://lucene.apache.org/solr/4_1_0/solr-core/org/apache/solr/handler/FieldAnalysisRequestHandler.html
|
22
|
-
def fieldtype_tokens(val, type)
|
23
|
-
target = 'analysis/field'
|
24
|
-
h = {'analysis.fieldtype' => name,
|
25
|
-
'analysis.fieldvalue' => val,
|
26
|
-
'analysis.query' => val,
|
27
|
-
}
|
28
|
-
resp = @core.get(target, h)
|
29
|
-
|
30
|
-
ftdata = resp['analysis']['field_types'][name][type]
|
31
|
-
rv = []
|
32
|
-
ftdata.last.each do |t|
|
33
|
-
pos = t['position'] - 1
|
34
|
-
text = t['text']
|
35
|
-
if rv[pos]
|
36
|
-
rv[pos] = Array[rv[pos]] << text
|
37
|
-
else
|
38
|
-
rv[pos] = text
|
39
|
-
end
|
40
|
-
end
|
41
|
-
rv
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
private :fieldtype_tokens
|
46
|
-
|
47
|
-
# Get an array of tokens as analyzed/transformed at index time
|
48
|
-
# Note that you may have multiple values at each token position if
|
49
|
-
# you use a synonym filter or a stemmer
|
50
|
-
# @param [String] ft the name of the fieldType (*not* the field)
|
51
|
-
# @param [String] val the search string to parse
|
52
|
-
# @return [Array] An array of tokens as produced by that index analysis chain
|
53
|
-
#
|
54
|
-
# @example Results when there's a stemmer
|
55
|
-
# c.fieldtype_index_tokens 'text', "That's Life"
|
56
|
-
# => [["that's", "that"], "life"]
|
57
|
-
#
|
58
|
-
def index_tokens(val)
|
59
|
-
fieldtype_tokens(val, 'index')
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
def index_input_valid?(val)
|
64
|
-
index_tokens(val)
|
65
|
-
rescue SimpleSolrClient::Schema::InvalidTokenError, RuntimeError => e
|
66
|
-
puts "IN HERE"
|
67
|
-
require 'pry'; binding.pry
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
# Get an array of tokens as analyzed/transformed at query time
|
72
|
-
# See #fieldtype_index_tokens
|
73
|
-
def query_tokens(val)
|
74
|
-
fieldtype_tokens(val, 'query')
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
-
end
|