solrbee 0.1.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77127390eb03bfbd53eec6916f7873fab49b6436f4acb94c528f2cec7ed5f76b
4
- data.tar.gz: '08ab2300881e0fdacaafa0007d1a17031a2b11bebfe2ade9cbf533a02a7b2b42'
3
+ metadata.gz: 11deb067a219ff325c0aa6dfaeb14422674cfd2a30338d14a1f00fa3f2081550
4
+ data.tar.gz: b6566f900e8a437feb379dba1e7f8de64e9c5a4b821cc501256ce0ee58da52e1
5
5
  SHA512:
6
- metadata.gz: 5642a45f1013a4ddf33f4a339f0990ec218d7c3ebce3e6b3e1a0811c81256a6c155df333d7894618de9cb4a8b9e7c9eac5f178237474e96cd2de5ec7193cee83
7
- data.tar.gz: bba5257728a581433cf72dbd4dce18ab5f8f7baea95afca7dca75c16f5fc17b509110c9e8ecb9a87713960f3eccf951d0bf11a0afe8b4ba01de2f331fcefd095
6
+ metadata.gz: aa65e21c6552dc4d4276ecfdc1a4089e69d3625af84d014cb6353183a9e145ed8adf34158b180e2c70d1718d211e35b32fbd545438bd13753d171484b1577010
7
+ data.tar.gz: 78fd833f50640f5f875be47160a87642f2b612c90906e3d349e68042f5d267b4b375727babcc8c2512c90006e7e858535e2382ecfc638d7dff333822f20e04c4
data/Gemfile CHANGED
@@ -1,3 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem 'rom', '5.2.4'
6
+ gem 'rom-http', git: 'https://github.com/rom-rb/rom-http.git'
data/Makefile CHANGED
@@ -2,13 +2,4 @@ SHELL = /bin/bash
2
2
 
3
3
  .PHONY : test
4
4
  test:
5
- bundle exec rake
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
@@ -25,7 +25,7 @@ Or install it yourself as:
25
25
 
26
26
  ## Usage
27
27
 
28
-
28
+ TODO
29
29
 
30
30
  ## Development
31
31
 
@@ -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
@@ -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,10 @@
1
+ Array.class_eval do
2
+
3
+ # Inspired by Rails's Array.wrap
4
+ def self.wrap(obj)
5
+ return [] if obj.nil?
6
+ return obj.to_ary if obj.respond_to?(:to_ary)
7
+ Array.new(1, obj)
8
+ end
9
+
10
+ end
@@ -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,15 @@
1
+ module ROM
2
+ module Solr
3
+ module Commands
4
+ class CreateDocuments < Create
5
+
6
+ relation :documents
7
+
8
+ def execute(docs)
9
+ relation.insert(docs)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module ROM
2
+ module Solr
3
+ module Commands
4
+ class DeleteDocuments < Delete
5
+
6
+ relation :documents
7
+
8
+ def execute(docs)
9
+ relation.delete(docs)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module ROM
2
+ module Solr
3
+ module Commands
4
+ class DeleteDocumentsByQuery < Delete
5
+
6
+ relation :documents
7
+
8
+ def execute(query)
9
+ relation.delete_by_query(query).response
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module ROM
2
+ module Solr
3
+ module Commands
4
+ class UpdateDocuments < Update
5
+
6
+ relation :documents
7
+
8
+ def execute(docs)
9
+ relation.update(docs)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ 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,12 @@
1
+ module ROM
2
+ module Solr
3
+ class DocumentsDataset < Dataset
4
+
5
+ configure do |config|
6
+ config.default_response_key = [:response, :docs]
7
+ config.default_base_path = 'select'
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module ROM
2
+ module Solr
3
+ class Gateway < ROM::HTTP::Gateway
4
+
5
+ adapter :solr
6
+
7
+ # @override
8
+ def dataset(name)
9
+ ROM::Solr.dataset_class(name).new(config)
10
+ end
11
+
12
+ end
13
+ end
14
+ 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,9 @@
1
+ module ROM
2
+ module Solr
3
+ class Repository < ROM::Repository
4
+
5
+ auto_struct false
6
+
7
+ end
8
+ end
9
+ 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,12 @@
1
+ module ROM
2
+ module Solr
3
+ class ResponseHandler
4
+
5
+ # @return [Hash] Parsed JSON object from Solr response body
6
+ def self.call(response, dataset)
7
+ JSON.parse(response.body, symbolize_names: true)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module ROM
2
+ module Solr
3
+ class Schema < ROM::Schema
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module ROM
2
+ module Solr
3
+ class SchemaInfoDataset < Dataset
4
+
5
+ configure do |config|
6
+ config.default_base_path = 'schema'
7
+ end
8
+
9
+ end
10
+ end
11
+ 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
@@ -1,31 +1,28 @@
1
1
  require "solrbee/version"
2
- require "solrbee/response"
3
- require "solrbee/request_params"
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
- class Error < StandardError; end
11
-
12
- # Single-valued field types
13
- STRING = "string"
14
- LONG = "plong"
15
- INT = "pint"
16
- DATE = "pdate"
17
- BOOLEAN = "boolean"
18
-
19
- # Multi-valued field types
20
- MSTRING = "strings"
21
- MLONG = "plongs"
22
- MINT = "pints"
23
- MDATE = "pdates"
24
- MBOOLEAN = "booleans"
25
-
26
- # Base URL
27
- def self.solr_url
28
- ENV.fetch('SOLR_URL', 'http://localhost:8983/solr').sub(/\/\z/, '')
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
@@ -1,3 +1,3 @@
1
1
  module Solrbee
2
- VERSION = "0.1.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -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 "hashie"
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.1.1
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-04 00:00:00.000000000 Z
11
+ date: 2020-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: hashie
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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