solrbee 0.1.1 → 0.4.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 +4 -4
- data/Gemfile +3 -0
- data/Makefile +1 -10
- data/README.md +1 -1
- data/config/api.yml +22 -0
- data/lib/rom/solr.rb +51 -0
- data/lib/rom/solr/array.rb +10 -0
- data/lib/rom/solr/commands.rb +17 -0
- data/lib/rom/solr/commands/create_documents.rb +15 -0
- data/lib/rom/solr/commands/delete_documents.rb +15 -0
- data/lib/rom/solr/commands/delete_documents_by_query.rb +15 -0
- data/lib/rom/solr/commands/update_documents.rb +15 -0
- data/lib/rom/solr/dataset.rb +72 -0
- data/lib/rom/solr/document_repo.rb +33 -0
- data/lib/rom/solr/documents_dataset.rb +12 -0
- data/lib/rom/solr/gateway.rb +14 -0
- data/lib/rom/solr/relation.rb +39 -0
- data/lib/rom/solr/relations/documents_relation.rb +160 -0
- data/lib/rom/solr/relations/schema_info_relation.rb +100 -0
- data/lib/rom/solr/repository.rb +9 -0
- data/lib/rom/solr/request_handler.rb +52 -0
- data/lib/rom/solr/response_handler.rb +12 -0
- data/lib/rom/solr/schema.rb +7 -0
- data/lib/rom/solr/schema_info_dataset.rb +11 -0
- data/lib/rom/solr/schema_info_repo.rb +45 -0
- data/lib/rom/solr/select_cursor.rb +56 -0
- data/lib/solrbee.rb +21 -24
- data/lib/solrbee/version.rb +1 -1
- data/solrbee.gemspec +2 -1
- data/test.sh +14 -0
- metadata +40 -9
- data/lib/solrbee/api_methods.rb +0 -85
- data/lib/solrbee/client.rb +0 -59
- data/lib/solrbee/cursor.rb +0 -37
- data/lib/solrbee/query.rb +0 -36
- data/lib/solrbee/request_params.rb +0 -13
- data/lib/solrbee/response.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11deb067a219ff325c0aa6dfaeb14422674cfd2a30338d14a1f00fa3f2081550
|
4
|
+
data.tar.gz: b6566f900e8a437feb379dba1e7f8de64e9c5a4b821cc501256ce0ee58da52e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa65e21c6552dc4d4276ecfdc1a4089e69d3625af84d014cb6353183a9e145ed8adf34158b180e2c70d1718d211e35b32fbd545438bd13753d171484b1577010
|
7
|
+
data.tar.gz: 78fd833f50640f5f875be47160a87642f2b612c90906e3d349e68042f5d267b4b375727babcc8c2512c90006e7e858535e2382ecfc638d7dff333822f20e04c4
|
data/Gemfile
CHANGED
data/Makefile
CHANGED
@@ -2,13 +2,4 @@ SHELL = /bin/bash
|
|
2
2
|
|
3
3
|
.PHONY : test
|
4
4
|
test:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
.PHONY : start-test-server
|
9
|
-
start-test-server:
|
10
|
-
docker run --rm -d -p 8983:8983 --name solrbee-test solr:8 solr-precreate solrbee
|
11
|
-
|
12
|
-
.PHONY : stop-test-server
|
13
|
-
stop-test-server:
|
14
|
-
docker stop solrbee-test
|
5
|
+
./test.sh
|
data/README.md
CHANGED
data/config/api.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
field_types:
|
2
|
+
path: fieldtypes
|
3
|
+
key: fieldTypes
|
4
|
+
field_type:
|
5
|
+
desc: GET /schema/fieldtype/[name]
|
6
|
+
path: fieldtypes/%{name}
|
7
|
+
args:
|
8
|
+
- name
|
9
|
+
key: fieldType
|
10
|
+
dynamic_fields:
|
11
|
+
desc: GET /schema/dynamicfields
|
12
|
+
path: dynamicfields
|
13
|
+
key: dynamicFields
|
14
|
+
dynamic_field:
|
15
|
+
desc: GET /schema/dynamicfields/[name]
|
16
|
+
args:
|
17
|
+
- name
|
18
|
+
path: dynamicfields/%{name}
|
19
|
+
key: dynamicField
|
20
|
+
copy_fields:
|
21
|
+
path: copyfields
|
22
|
+
key: copyFields
|
data/lib/rom/solr.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rom-http'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module ROM
|
5
|
+
module Solr
|
6
|
+
|
7
|
+
def self.dataset_class(name)
|
8
|
+
prefix = name.to_s.split(/[_\/]/).map(&:capitalize).join('')
|
9
|
+
const_name = "#{prefix}Dataset"
|
10
|
+
const_defined?(const_name, false) ? const_get(const_name, false) : Dataset
|
11
|
+
end
|
12
|
+
|
13
|
+
module Types
|
14
|
+
include ROM::HTTP::Types
|
15
|
+
end
|
16
|
+
|
17
|
+
UUID = Types::String.default { SecureRandom.uuid }
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Utilities
|
23
|
+
require_relative 'solr/array'
|
24
|
+
|
25
|
+
# Handlers
|
26
|
+
require_relative 'solr/request_handler'
|
27
|
+
require_relative 'solr/response_handler'
|
28
|
+
|
29
|
+
# Datasets
|
30
|
+
require_relative 'solr/dataset'
|
31
|
+
require_relative 'solr/documents_dataset'
|
32
|
+
require_relative 'solr/schema_info_dataset'
|
33
|
+
|
34
|
+
# Gateway
|
35
|
+
require_relative 'solr/gateway'
|
36
|
+
|
37
|
+
# Schemas
|
38
|
+
require_relative 'solr/schema'
|
39
|
+
|
40
|
+
# Relations
|
41
|
+
require_relative 'solr/relation'
|
42
|
+
|
43
|
+
# Repositories
|
44
|
+
require_relative 'solr/repository'
|
45
|
+
require_relative 'solr/schema_info_repo'
|
46
|
+
require_relative 'solr/document_repo'
|
47
|
+
|
48
|
+
# Commands
|
49
|
+
require_relative 'solr/commands'
|
50
|
+
|
51
|
+
ROM.register_adapter(:solr, ROM::Solr)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ROM
|
2
|
+
module Solr
|
3
|
+
module Commands
|
4
|
+
class Create < ROM::Commands::Create
|
5
|
+
adapter :solr
|
6
|
+
end
|
7
|
+
|
8
|
+
class Update < ROM::Commands::Update
|
9
|
+
adapter :solr
|
10
|
+
end
|
11
|
+
|
12
|
+
class Delete < ROM::Commands::Delete
|
13
|
+
adapter :solr
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ROM
|
2
|
+
module Solr
|
3
|
+
class Dataset < ROM::HTTP::Dataset
|
4
|
+
|
5
|
+
setting :default_response_key, reader: true
|
6
|
+
setting :default_content_type, reader: true
|
7
|
+
setting :default_base_path, reader: true
|
8
|
+
|
9
|
+
configure do |config|
|
10
|
+
config.default_response_handler = ResponseHandler
|
11
|
+
config.default_request_handler = RequestHandler
|
12
|
+
end
|
13
|
+
|
14
|
+
option :response_key, default: proc { self.class.default_response_key }
|
15
|
+
option :request_data, type: Types::String, default: proc { EMPTY_STRING }
|
16
|
+
option :content_type, type: Types::String, default: proc { self.class.default_content_type }
|
17
|
+
option :base_path, type: Types::Path, default: proc { self.class.default_base_path || EMPTY_STRING }
|
18
|
+
|
19
|
+
# @override Query parameters are valid with POST, too.
|
20
|
+
def uri
|
21
|
+
uri_s = [options[:uri], path].compact.reject(&:empty?).join('/')
|
22
|
+
|
23
|
+
URI(uri_s).tap do |u|
|
24
|
+
u.query = param_encoder.call(params) if has_params?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @override
|
29
|
+
def each(&block)
|
30
|
+
return to_enum unless block_given?
|
31
|
+
|
32
|
+
enumerable_data.each(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def with_request_data(data)
|
36
|
+
with_options(request_data: data)
|
37
|
+
end
|
38
|
+
|
39
|
+
def with_response_key(*path)
|
40
|
+
with_options(response_key: path)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Copies and makes private superclass #response method
|
44
|
+
alias_method :__response__, :response
|
45
|
+
private :__response__
|
46
|
+
|
47
|
+
# @override Cache response by default
|
48
|
+
def response
|
49
|
+
cache.fetch_or_store(:response) { __response__ }
|
50
|
+
end
|
51
|
+
|
52
|
+
def has_request_data?
|
53
|
+
!request_data.nil? && !request_data.empty?
|
54
|
+
end
|
55
|
+
|
56
|
+
def has_params?
|
57
|
+
params.any?
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def enumerable_data
|
63
|
+
Array.wrap(response_key ? response.dig(*response_key) : response)
|
64
|
+
end
|
65
|
+
|
66
|
+
def cache
|
67
|
+
@cache ||= Concurrent::Map.new
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ROM
|
2
|
+
module Solr
|
3
|
+
class DocumentRepo < Repository[:documents]
|
4
|
+
|
5
|
+
auto_struct false
|
6
|
+
|
7
|
+
def find(id)
|
8
|
+
documents.by_unique_key(id).one!
|
9
|
+
end
|
10
|
+
|
11
|
+
def search
|
12
|
+
documents
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
documents.all
|
17
|
+
end
|
18
|
+
|
19
|
+
def create(docs)
|
20
|
+
documents.command(:create_documents).call(docs)
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete(docs)
|
24
|
+
documents.command(:delete_documents).call(docs)
|
25
|
+
end
|
26
|
+
|
27
|
+
def update(docs)
|
28
|
+
documents.command(:update_documents).call(docs)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ROM
|
2
|
+
module Solr
|
3
|
+
class Relation < ROM::HTTP::Relation
|
4
|
+
|
5
|
+
adapter :solr
|
6
|
+
auto_struct false
|
7
|
+
auto_map false
|
8
|
+
|
9
|
+
forward :with_response_key
|
10
|
+
|
11
|
+
option :output_schema, default: ->{ NOOP_OUTPUT_SCHEMA }
|
12
|
+
|
13
|
+
def wt(format)
|
14
|
+
add_params(wt: Types::Coercible::String[format])
|
15
|
+
end
|
16
|
+
alias_method :format, :wt
|
17
|
+
|
18
|
+
def log_params_list(log_params)
|
19
|
+
lplist = log_params.nil? ? nil : Array.wrap(log_params).join(',')
|
20
|
+
|
21
|
+
add_params(logParamsList: lplist)
|
22
|
+
end
|
23
|
+
alias_method :log_params, :log_params_list
|
24
|
+
|
25
|
+
def count
|
26
|
+
to_enum.count
|
27
|
+
end
|
28
|
+
|
29
|
+
def response
|
30
|
+
dataset.response
|
31
|
+
end
|
32
|
+
|
33
|
+
def params
|
34
|
+
dataset.params.dup
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'rom/solr/select_cursor'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module Solr
|
5
|
+
class DocumentsRelation < Relation
|
6
|
+
|
7
|
+
schema(:documents) { }
|
8
|
+
|
9
|
+
# @override
|
10
|
+
def each(&block)
|
11
|
+
return to_enum unless block_given?
|
12
|
+
|
13
|
+
SelectCursor.new(dataset).each(&block)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @override FIXME: Get from Solr schema unique key
|
17
|
+
def primary_key
|
18
|
+
:id
|
19
|
+
end
|
20
|
+
|
21
|
+
def by_unique_key(id)
|
22
|
+
q('%s:%s' % [ primary_key, id ])
|
23
|
+
end
|
24
|
+
|
25
|
+
def all
|
26
|
+
q('*:*')
|
27
|
+
end
|
28
|
+
|
29
|
+
# @override
|
30
|
+
def count
|
31
|
+
num_found_exact ? num_found : super
|
32
|
+
end
|
33
|
+
|
34
|
+
def num_found
|
35
|
+
response.dig(:response, :numFound)
|
36
|
+
end
|
37
|
+
|
38
|
+
def num_found_exact
|
39
|
+
response.dig(:response, :numFoundExact)
|
40
|
+
end
|
41
|
+
|
42
|
+
def insert(docs)
|
43
|
+
data = Array.wrap(docs).map do |doc|
|
44
|
+
doc.transform_keys!(&:to_sym)
|
45
|
+
doc[:id] ||= UUID[]
|
46
|
+
end
|
47
|
+
|
48
|
+
update(data)
|
49
|
+
end
|
50
|
+
|
51
|
+
def update(docs)
|
52
|
+
with_options(
|
53
|
+
base_path: 'update/json/docs',
|
54
|
+
content_type: 'application/json',
|
55
|
+
request_data: JSON.dump(docs)
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete(docs)
|
60
|
+
ids = Array.wrap(docs).map { |doc| doc.transform_keys(&:to_sym) }.map(&:id)
|
61
|
+
|
62
|
+
with_options(
|
63
|
+
base_path: 'update',
|
64
|
+
content_type: 'application/json',
|
65
|
+
request_data: JSON.dump(delete: ids)
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Params
|
71
|
+
#
|
72
|
+
def q(query)
|
73
|
+
add_params(q: Types::String[query])
|
74
|
+
end
|
75
|
+
alias_method :query, :q
|
76
|
+
|
77
|
+
def fq(*filter)
|
78
|
+
add_params(fq: filter)
|
79
|
+
end
|
80
|
+
alias_method :filter, :fq
|
81
|
+
|
82
|
+
def fl(*fields)
|
83
|
+
add_params(fl: fields.join(','))
|
84
|
+
end
|
85
|
+
alias_method :fields, :fl
|
86
|
+
|
87
|
+
def cache(enabled = true)
|
88
|
+
add_params(cache: Types::Bool[enabled])
|
89
|
+
end
|
90
|
+
|
91
|
+
def segment_terminate_early(enabled = true)
|
92
|
+
add_params(segmentTerminateEarly: Types::Bool[enabled])
|
93
|
+
end
|
94
|
+
|
95
|
+
def time_allowed(millis)
|
96
|
+
add_params(timeAllowed: Types::Coercible::Integer[millis])
|
97
|
+
end
|
98
|
+
|
99
|
+
def explain_other(query)
|
100
|
+
add_params(explainOther: Types::String[query])
|
101
|
+
end
|
102
|
+
|
103
|
+
def omit_header(omit = true)
|
104
|
+
add_params(omitHeader: Types::Bool[omit])
|
105
|
+
end
|
106
|
+
|
107
|
+
def start(offset)
|
108
|
+
add_params(start: Types::Coercible::Integer[offset])
|
109
|
+
end
|
110
|
+
|
111
|
+
def sort(*criteria)
|
112
|
+
add_params(sort: criteria.join(','))
|
113
|
+
end
|
114
|
+
|
115
|
+
def rows(num)
|
116
|
+
add_params(rows: Types::Coercible::Integer[num])
|
117
|
+
end
|
118
|
+
alias_method :limit, :rows
|
119
|
+
|
120
|
+
def def_type(value)
|
121
|
+
add_params(defType: Types::Coercible::String[value])
|
122
|
+
end
|
123
|
+
|
124
|
+
def debug(setting)
|
125
|
+
type = Types::Coercible::String
|
126
|
+
.enum('query', 'timing', 'results', 'all', 'true')
|
127
|
+
|
128
|
+
add_params(debug: type[setting])
|
129
|
+
end
|
130
|
+
|
131
|
+
def echo_params(setting)
|
132
|
+
type = Types::Coercible::String.enum('explicit', 'all', 'none')
|
133
|
+
add_params(echoParams: type[setting])
|
134
|
+
end
|
135
|
+
|
136
|
+
def min_exact_count(num)
|
137
|
+
add_params(minExactCount: Types::Coercible::Integer[num])
|
138
|
+
end
|
139
|
+
|
140
|
+
def commit(value = true)
|
141
|
+
add_params(commit: Types::Bool[value])
|
142
|
+
end
|
143
|
+
|
144
|
+
def commit_within(millis)
|
145
|
+
return self if millis.nil?
|
146
|
+
|
147
|
+
add_params(commitWithin: Types::Coercible::Integer[millis])
|
148
|
+
end
|
149
|
+
|
150
|
+
def overwrite(value = true)
|
151
|
+
add_params(overwrite: Types::Bool[value])
|
152
|
+
end
|
153
|
+
|
154
|
+
def expunge_deletes(value = true)
|
155
|
+
add_params(expungeDeletes: Types::Bool[value])
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module ROM
|
2
|
+
module Solr
|
3
|
+
class SchemaInfoRelation < Relation
|
4
|
+
|
5
|
+
schema(:schema_info) do
|
6
|
+
# no-op
|
7
|
+
end
|
8
|
+
|
9
|
+
def show_defaults(show = true)
|
10
|
+
add_params(showDefaults: Types::Bool[show])
|
11
|
+
end
|
12
|
+
|
13
|
+
def include_dynamic(enabled = true)
|
14
|
+
add_params(includeDynamic: Types::Bool[enabled])
|
15
|
+
end
|
16
|
+
|
17
|
+
def info
|
18
|
+
with_response_key(:schema)
|
19
|
+
end
|
20
|
+
|
21
|
+
def copy_fields
|
22
|
+
with_options(
|
23
|
+
path: :copyfields,
|
24
|
+
response_key: :copyFields
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def dynamic_fields
|
29
|
+
with_options(
|
30
|
+
path: :dynamicfields,
|
31
|
+
response_key: :dynamicFields
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def dynamic_field(name)
|
36
|
+
with_options(
|
37
|
+
path: "dynamicfields/#{name}",
|
38
|
+
response_key: :dynamicField
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def similarity
|
43
|
+
with_options(
|
44
|
+
path: :similarity,
|
45
|
+
response_key: :similarity
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def unique_key
|
50
|
+
with_options(
|
51
|
+
path: :uniquekey,
|
52
|
+
response_key: :uniqueKey
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def version
|
57
|
+
with_options(
|
58
|
+
path: :version,
|
59
|
+
response_key: :version
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def schema_name
|
64
|
+
with_options(
|
65
|
+
path: :name,
|
66
|
+
response_key: :name
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def fields
|
71
|
+
with_options(
|
72
|
+
path: :fields,
|
73
|
+
response_key: :fields
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
def field(name)
|
78
|
+
with_options(
|
79
|
+
path: "fields/#{name}",
|
80
|
+
response_key: :field
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def field_types
|
85
|
+
with_options(
|
86
|
+
path: :fieldtypes,
|
87
|
+
response_key: :fieldTypes
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
def field_type(name)
|
92
|
+
with_options(
|
93
|
+
path: "fieldtypes/#{name}",
|
94
|
+
response_key: :fieldType
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ROM
|
2
|
+
module Solr
|
3
|
+
class RequestHandler
|
4
|
+
|
5
|
+
def self.call(dataset)
|
6
|
+
new(dataset).execute
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :dataset
|
10
|
+
|
11
|
+
def initialize(dataset)
|
12
|
+
@dataset = dataset
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme.eql?('https')) do |http|
|
17
|
+
http.request(request)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def request
|
22
|
+
request_class.new(uri.request_uri, headers).tap do |req|
|
23
|
+
if dataset.has_request_data?
|
24
|
+
req.body = dataset.request_data
|
25
|
+
req.content_type = dataset.content_type
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def headers
|
31
|
+
dataset.headers.transform_keys(&:to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
def uri
|
35
|
+
@uri ||= URI(dataset.uri).tap do |u|
|
36
|
+
if dataset.has_params?
|
37
|
+
u.query ||= URI.encode_www_form(dataset.params)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def request_class
|
43
|
+
if dataset.has_request_data?
|
44
|
+
Net::HTTP::Post
|
45
|
+
else
|
46
|
+
Net::HTTP::Get
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ROM
|
2
|
+
module Solr
|
3
|
+
class SchemaInfoRepo < Repository[:schema_info]
|
4
|
+
|
5
|
+
auto_struct false
|
6
|
+
|
7
|
+
%i[ schema_name similarity unique_key version ].each do |name|
|
8
|
+
define_method name, ->{ schema_info.send(name).one! }
|
9
|
+
end
|
10
|
+
|
11
|
+
def info
|
12
|
+
schema_info.info.one!
|
13
|
+
end
|
14
|
+
|
15
|
+
def fields(dynamic: true, defaults: true)
|
16
|
+
schema_info.fields.show_defaults(defaults).include_dynamic(dynamic)
|
17
|
+
end
|
18
|
+
|
19
|
+
def field(name, defaults: true)
|
20
|
+
schema_info.field(name).show_defaults(defaults).one
|
21
|
+
end
|
22
|
+
|
23
|
+
def field_types(defaults: true)
|
24
|
+
schema_info.field_types.show_defaults(defaults)
|
25
|
+
end
|
26
|
+
|
27
|
+
def field_type(name, defaults: true)
|
28
|
+
schema_info.field_type(name).show_defaults(defaults).one
|
29
|
+
end
|
30
|
+
|
31
|
+
def dynamic_fields
|
32
|
+
schema_info.dynamic_fields
|
33
|
+
end
|
34
|
+
|
35
|
+
def dynamic_field(name, defaults: true)
|
36
|
+
schema_info.dynamic_field(name).show_defaults(defaults).one
|
37
|
+
end
|
38
|
+
|
39
|
+
def copy_fields
|
40
|
+
schema_info.copy_fields
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module Solr
|
5
|
+
#
|
6
|
+
# Wraps a DocumentsDataset to provide pagination with a cursor.
|
7
|
+
#
|
8
|
+
class SelectCursor < SimpleDelegator
|
9
|
+
|
10
|
+
def initialize(dataset)
|
11
|
+
params = { cursorMark: '*' }
|
12
|
+
|
13
|
+
# Sort must include a sort on unique key (id).
|
14
|
+
sort = dataset.params[:sort]
|
15
|
+
unless /\bid\b/ =~ sort
|
16
|
+
params[:sort] = Array.wrap(sort).append('id ASC').join(',')
|
17
|
+
end
|
18
|
+
|
19
|
+
super dataset.add_params(params)
|
20
|
+
end
|
21
|
+
|
22
|
+
def each(&block)
|
23
|
+
return to_enum unless block_given?
|
24
|
+
|
25
|
+
while true
|
26
|
+
__getobj__.each(&block)
|
27
|
+
|
28
|
+
break if last_page?
|
29
|
+
|
30
|
+
move_cursor
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def cursor_mark
|
35
|
+
params[:cursorMark]
|
36
|
+
end
|
37
|
+
|
38
|
+
def next_cursor_mark
|
39
|
+
response[:nextCursorMark]
|
40
|
+
end
|
41
|
+
|
42
|
+
def last_page?
|
43
|
+
cursor_mark == next_cursor_mark
|
44
|
+
end
|
45
|
+
|
46
|
+
def move_cursor
|
47
|
+
__setobj__(next_page)
|
48
|
+
end
|
49
|
+
|
50
|
+
def next_page
|
51
|
+
__getobj__.add_params(cursorMark: next_cursor_mark)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/solrbee.rb
CHANGED
@@ -1,31 +1,28 @@
|
|
1
1
|
require "solrbee/version"
|
2
|
-
|
3
|
-
require "
|
4
|
-
require "solrbee/query"
|
5
|
-
require "solrbee/client"
|
6
|
-
require "solrbee/cursor"
|
2
|
+
|
3
|
+
require "rom/solr"
|
7
4
|
|
8
5
|
module Solrbee
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
7
|
+
DEFAULT_URI = ENV.fetch('SOLR_URL', 'http://localhost:8983/solr').freeze
|
8
|
+
|
9
|
+
def self.documents
|
10
|
+
ROM::Solr::DocumentRepo.new(container)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.schema_info
|
14
|
+
ROM::Solr::SchemaInfoRepo.new(container)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.container(uri: DEFAULT_URI)
|
18
|
+
ROM.container(:solr, uri: uri) do |config|
|
19
|
+
config.auto_registration(
|
20
|
+
File.expand_path('../rom/solr/', __FILE__),
|
21
|
+
namespace: 'ROM::Solr'
|
22
|
+
)
|
23
|
+
|
24
|
+
yield config if block_given?
|
25
|
+
end
|
29
26
|
end
|
30
27
|
|
31
28
|
end
|
data/lib/solrbee/version.rb
CHANGED
data/solrbee.gemspec
CHANGED
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
-
spec.add_dependency "
|
25
|
+
spec.add_dependency "rom"
|
26
|
+
spec.add_dependency "rom-http"
|
26
27
|
|
27
28
|
spec.add_development_dependency "bundler"
|
28
29
|
spec.add_development_dependency "rake"
|
data/test.sh
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
docker run --rm -d -p 8983:8983 --name solrbee-test solr:8 solr-precreate solrbee
|
4
|
+
|
5
|
+
while ! curl -fs http://localhost:8983/solr/solrbee/admin/ping 2>/dev/null ;
|
6
|
+
do sleep 1
|
7
|
+
done
|
8
|
+
|
9
|
+
SOLR_URL=http://localhost:8983/solr/solrbee bundle exec rake
|
10
|
+
code=$?
|
11
|
+
|
12
|
+
docker stop solrbee-test
|
13
|
+
|
14
|
+
exit $code
|
metadata
CHANGED
@@ -1,17 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solrbee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Chandek-Stark
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
11
|
+
date: 2020-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rom
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rom-http
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - ">="
|
@@ -96,15 +110,32 @@ files:
|
|
96
110
|
- Rakefile
|
97
111
|
- bin/console
|
98
112
|
- bin/setup
|
113
|
+
- config/api.yml
|
114
|
+
- lib/rom/solr.rb
|
115
|
+
- lib/rom/solr/array.rb
|
116
|
+
- lib/rom/solr/commands.rb
|
117
|
+
- lib/rom/solr/commands/create_documents.rb
|
118
|
+
- lib/rom/solr/commands/delete_documents.rb
|
119
|
+
- lib/rom/solr/commands/delete_documents_by_query.rb
|
120
|
+
- lib/rom/solr/commands/update_documents.rb
|
121
|
+
- lib/rom/solr/dataset.rb
|
122
|
+
- lib/rom/solr/document_repo.rb
|
123
|
+
- lib/rom/solr/documents_dataset.rb
|
124
|
+
- lib/rom/solr/gateway.rb
|
125
|
+
- lib/rom/solr/relation.rb
|
126
|
+
- lib/rom/solr/relations/documents_relation.rb
|
127
|
+
- lib/rom/solr/relations/schema_info_relation.rb
|
128
|
+
- lib/rom/solr/repository.rb
|
129
|
+
- lib/rom/solr/request_handler.rb
|
130
|
+
- lib/rom/solr/response_handler.rb
|
131
|
+
- lib/rom/solr/schema.rb
|
132
|
+
- lib/rom/solr/schema_info_dataset.rb
|
133
|
+
- lib/rom/solr/schema_info_repo.rb
|
134
|
+
- lib/rom/solr/select_cursor.rb
|
99
135
|
- lib/solrbee.rb
|
100
|
-
- lib/solrbee/api_methods.rb
|
101
|
-
- lib/solrbee/client.rb
|
102
|
-
- lib/solrbee/cursor.rb
|
103
|
-
- lib/solrbee/query.rb
|
104
|
-
- lib/solrbee/request_params.rb
|
105
|
-
- lib/solrbee/response.rb
|
106
136
|
- lib/solrbee/version.rb
|
107
137
|
- solrbee.gemspec
|
138
|
+
- test.sh
|
108
139
|
homepage: https://github.com/dchandekstark/solrbee
|
109
140
|
licenses:
|
110
141
|
- MIT
|
data/lib/solrbee/api_methods.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
module Solrbee
|
2
|
-
module ApiMethods
|
3
|
-
|
4
|
-
def schema_name
|
5
|
-
response = get('/schema/name')
|
6
|
-
response.name
|
7
|
-
end
|
8
|
-
|
9
|
-
def schema_version
|
10
|
-
response = get('/schema/version')
|
11
|
-
response.version
|
12
|
-
end
|
13
|
-
|
14
|
-
def schema
|
15
|
-
response = get('/schema')
|
16
|
-
response.schema
|
17
|
-
end
|
18
|
-
|
19
|
-
def fields(**params)
|
20
|
-
response = get('/schema/fields', **params)
|
21
|
-
response.fields
|
22
|
-
end
|
23
|
-
|
24
|
-
def field(field_name, **params)
|
25
|
-
response = get('/schema/fields/%s' % field_name, **params)
|
26
|
-
response.field
|
27
|
-
end
|
28
|
-
|
29
|
-
def unique_key
|
30
|
-
@unique_key ||= get('/schema/uniquekey').uniqueKey
|
31
|
-
end
|
32
|
-
|
33
|
-
def field_types(**params)
|
34
|
-
response = get('/schema/fieldtypes', **params)
|
35
|
-
response.fieldTypes
|
36
|
-
end
|
37
|
-
|
38
|
-
def field_type(field_name, **params)
|
39
|
-
response = get('/schema/fieldtypes/%s' % field_name, **params)
|
40
|
-
response.fieldType
|
41
|
-
end
|
42
|
-
|
43
|
-
def field_names
|
44
|
-
fields.map(&:name)
|
45
|
-
end
|
46
|
-
|
47
|
-
def field_type_names
|
48
|
-
field_types.map(&:name)
|
49
|
-
end
|
50
|
-
|
51
|
-
def add_field(field)
|
52
|
-
post('/schema', {"add-field"=>field})
|
53
|
-
end
|
54
|
-
|
55
|
-
def delete_field(field)
|
56
|
-
post('/schema', {"delete-field"=>{"name"=>field.name}})
|
57
|
-
end
|
58
|
-
|
59
|
-
def replace_field(field)
|
60
|
-
post('/schema', {"replace-field"=>field})
|
61
|
-
end
|
62
|
-
|
63
|
-
# "real-time get"
|
64
|
-
# Note: Using POST here for simpler params.
|
65
|
-
def get_by_id(*ids)
|
66
|
-
response = post('/get', params: { id: ids })
|
67
|
-
response.doc || response.docs
|
68
|
-
end
|
69
|
-
|
70
|
-
def index(*docs, **params)
|
71
|
-
post('/update/json/docs', docs, **params)
|
72
|
-
end
|
73
|
-
alias_method :add, :index
|
74
|
-
alias_method :update, :index
|
75
|
-
|
76
|
-
def delete(*ids)
|
77
|
-
post('/update', delete: ids)
|
78
|
-
end
|
79
|
-
|
80
|
-
def query(params)
|
81
|
-
post('/query', Query.new(params))
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|
data/lib/solrbee/client.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
require "net/http"
|
2
|
-
require "uri"
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
require "solrbee/api_methods"
|
6
|
-
|
7
|
-
module Solrbee
|
8
|
-
class Client
|
9
|
-
include ApiMethods
|
10
|
-
|
11
|
-
attr_reader :collection, :uri
|
12
|
-
|
13
|
-
def initialize(collection)
|
14
|
-
@collection = collection
|
15
|
-
@uri = URI(Solrbee.solr_url).tap do |u|
|
16
|
-
u.path += '/%s' % URI.encode_www_form_component(collection)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def connection
|
21
|
-
Net::HTTP.new(uri.host, uri.port).tap do |http|
|
22
|
-
http.use_ssl = true if uri.scheme == 'https'
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# :get -> Net::HTTP::Get
|
27
|
-
def request_class(method)
|
28
|
-
Net::HTTP.const_get(method.to_s.downcase.capitalize)
|
29
|
-
end
|
30
|
-
|
31
|
-
def request(method, path, **params)
|
32
|
-
req_uri = uri.dup
|
33
|
-
req_uri.path += path
|
34
|
-
unless params.empty?
|
35
|
-
req_uri.query = URI.encode_www_form RequestParams.new(params)
|
36
|
-
end
|
37
|
-
req = request_class(method).new(req_uri, {'Accept'=>'application/json'})
|
38
|
-
yield req if block_given?
|
39
|
-
res = connection.request(req)
|
40
|
-
Response.new JSON.parse(res.body)
|
41
|
-
end
|
42
|
-
|
43
|
-
def get(path, **params)
|
44
|
-
request(:get, path, **params)
|
45
|
-
end
|
46
|
-
|
47
|
-
def post(path, data, **params)
|
48
|
-
request(:post, path, **params) do |req|
|
49
|
-
req['Content-Type'] = 'application/json'
|
50
|
-
req.body = JSON.dump(data)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def cursor
|
55
|
-
Cursor.new(self)
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
data/lib/solrbee/cursor.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
module Solrbee
|
2
|
-
#
|
3
|
-
# Summary
|
4
|
-
#
|
5
|
-
# > client = Solrbee::Client.new('mycollection'))
|
6
|
-
# > cursor = Solrbee::Cursor.new(client)
|
7
|
-
# > query = { query: 'foo:bar', sort: 'title ASC', limit: 10 }
|
8
|
-
# > results = cursor.execute(query)
|
9
|
-
# > results.each do |doc|
|
10
|
-
# ...
|
11
|
-
# > end
|
12
|
-
#
|
13
|
-
class Cursor
|
14
|
-
|
15
|
-
attr_reader :client
|
16
|
-
|
17
|
-
def initialize(client)
|
18
|
-
@client = client
|
19
|
-
end
|
20
|
-
|
21
|
-
# @return [Enumerator] an enumerator of query results
|
22
|
-
def execute(query)
|
23
|
-
Enumerator.new do |yielder|
|
24
|
-
q = Query.cursor(query, client.unique_key)
|
25
|
-
|
26
|
-
while true
|
27
|
-
response = client.query(q)
|
28
|
-
break if response.num_found == 0
|
29
|
-
break if response.nextCursorMark == q.params.cursorMark
|
30
|
-
response.docs.each { |doc| yielder << doc }
|
31
|
-
q.params.cursorMark = response.nextCursorMark
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
data/lib/solrbee/query.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'hashie'
|
2
|
-
|
3
|
-
module Solrbee
|
4
|
-
#
|
5
|
-
# A query targeting the JSON Request API.
|
6
|
-
#
|
7
|
-
class Query < Hashie::Trash
|
8
|
-
|
9
|
-
property :query, from: :q, default: '*:*'
|
10
|
-
property :filter, from: :fq
|
11
|
-
property :limit, from: :rows, default: 10
|
12
|
-
property :fields, from: :fl
|
13
|
-
property :sort
|
14
|
-
property :offset, from: :start
|
15
|
-
property :facet
|
16
|
-
property :queries
|
17
|
-
property :params, default: {}
|
18
|
-
|
19
|
-
# Build a query for a Cursor
|
20
|
-
def self.cursor(params, unique_key)
|
21
|
-
Query.new(params).tap do |q|
|
22
|
-
q.delete(:offset) # incompatible with cursor
|
23
|
-
q.params[:cursorMark] = '*' # initial cursor mark
|
24
|
-
|
25
|
-
# Sort on unique key is required for cursor
|
26
|
-
q.sort = "#{unique_key} ASC" unless q.sort
|
27
|
-
unless q.sort =~ /\b#{unique_key}\b/
|
28
|
-
clauses = q.sort.split(/,/)
|
29
|
-
clauses << "#{unique_key} ASC"
|
30
|
-
q.sort = clauses.join(',')
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'hashie'
|
2
|
-
|
3
|
-
module Solrbee
|
4
|
-
#
|
5
|
-
# For marshalling various API request query parameters
|
6
|
-
#
|
7
|
-
class RequestParams < Hashie::Trash
|
8
|
-
property :showDefaults, from: :show_defaults
|
9
|
-
property :includeDynamic, from: :include_dynamic
|
10
|
-
property :fl
|
11
|
-
property :commit
|
12
|
-
end
|
13
|
-
end
|
data/lib/solrbee/response.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'hashie'
|
2
|
-
|
3
|
-
module Solrbee
|
4
|
-
class Response < Hashie::Mash
|
5
|
-
|
6
|
-
disable_warnings
|
7
|
-
|
8
|
-
def header
|
9
|
-
responseHeader
|
10
|
-
end
|
11
|
-
|
12
|
-
def num_found
|
13
|
-
response.numFound
|
14
|
-
end
|
15
|
-
|
16
|
-
def docs
|
17
|
-
response.docs
|
18
|
-
end
|
19
|
-
|
20
|
-
def doc
|
21
|
-
response.doc
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|