solrbee 0.2.1 → 0.3.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: ba9c7b336f903632e73bba3dc8b7689a11581dbac82db1a5e766edc427f12a1d
4
- data.tar.gz: 508e84b7cafb3e65a71eb95d6e8afe1a76df69cced60ad4d7f770685cd63caa4
3
+ metadata.gz: 77e7ebc45077bb8016d699124b9d4de397adba4d6166e0b3f64bb07693c51a3f
4
+ data.tar.gz: 846ea941962ac61ac49195bc0a05ef4356fbc0937a96055af43320c833b41b5d
5
5
  SHA512:
6
- metadata.gz: 47e306541ae1e6551b3a45212045970533d4d6fee01f6ac70c291d08bc618f9a964d513c6517d534e66568c60605213a0a4aa33c3bd2dd20660f27f761dcb40f
7
- data.tar.gz: 6cf7560f0015d0d564e0e6c897f34c4b90a1d76e962f729cdc4a565775589c456f1c15d2d17066f2e0b5f5c42b0b24c32ff9814040e353694e36680291751cea
6
+ metadata.gz: 278f91339f713389ab9858471f35f8a72d07ae1e00083e931cade7af50aee540ba8abf1bd42a79f1a1ffa11ab3b081f8a3231035642ff61091abc7f8f3306da5
7
+ data.tar.gz: a143efa02fed4ee7e10c063bf4c4db6df6df5f9bbf40ba820c004c4961e206545d980ed615f566b99c996f30db184a49fce7a005d990ebbca4b9028cddadaebf
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem "rom-http", git: "https://github.com/rom-rb/rom-http.git"
@@ -0,0 +1,45 @@
1
+ v1:
2
+ ping:
3
+ path: /admin/ping
4
+ response_key: status
5
+
6
+ schema:
7
+ path: /schema
8
+ response_key: schema
9
+
10
+ schema_name:
11
+ path: /schema/name
12
+ response_key: name
13
+
14
+ schema_version:
15
+ path: /schema/version
16
+ response_key: version
17
+
18
+ fields:
19
+ path: /schema/fields
20
+ response_key: fields
21
+
22
+ field:
23
+ path: /schema/fields/%{name}
24
+ response_key: field
25
+
26
+ unique_key:
27
+ path: /schema/uniquekey
28
+ response_key: uniqueKey
29
+
30
+ field_types:
31
+ path: /schema/fieldtypes
32
+ response_key: fieldTypes
33
+
34
+ field_type:
35
+ path: /schema/fieldtypes/%{name}
36
+ response_key: fieldType
37
+
38
+ update:
39
+ path: /update
40
+
41
+ update_json:
42
+ path: /update/json
43
+
44
+ update_json_docs:
45
+ path: /update/json/docs
@@ -0,0 +1,22 @@
1
+ require 'rom-http'
2
+
3
+ require_relative 'solr/request'
4
+ require_relative 'solr/response'
5
+
6
+ require_relative 'solr/dataset'
7
+ require_relative 'solr/datasets/select_dataset'
8
+
9
+ require_relative 'solr/gateway'
10
+
11
+ require_relative 'solr/schemaless'
12
+
13
+ require_relative 'solr/relation'
14
+ require_relative 'solr/relations/schema_relation'
15
+ require_relative 'solr/relations/select_relation'
16
+
17
+ module ROM
18
+ module Solr
19
+ end
20
+
21
+ register_adapter(:solr, ROM::Solr)
22
+ end
@@ -0,0 +1,93 @@
1
+ module ROM
2
+ module Solr
3
+ class Dataset < ROM::HTTP::Dataset
4
+
5
+ # Key or array of keys to pass to response.dig(*keys)
6
+ # for enumeration of the dataset values.
7
+ setting :default_enum_on, reader: true
8
+ option :enum_on, default: ->{ self.class.default_enum_on }
9
+
10
+ # Default query parameters
11
+ setting :default_params, EMPTY_HASH, reader: true
12
+ option :params, type: Types::Hash, default: ->{ self.class.default_params }
13
+
14
+ # Request and response handlers
15
+ config.default_response_handler = Response
16
+ config.default_request_handler = Request
17
+
18
+ # @override Handles multiple path segments and nils
19
+ def with_path(segments)
20
+ s = Array.wrap(segments)
21
+ return self if s.empty?
22
+ with_options(path: s.compact.join('/'))
23
+ end
24
+
25
+ def with_enum_on(keys)
26
+ k = Array.wrap(keys)
27
+ return self if k.empty?
28
+ with_options(enum_on: k)
29
+ end
30
+
31
+ # Coerce param value to an Array and set new value
32
+ # to set union with other Array of values.
33
+ def add_param_values(key, val)
34
+ new_val = Array.wrap(params[key]) | Array.wrap(val)
35
+ add_params(key => new_val)
36
+ end
37
+
38
+ # @override
39
+ def add_params(new_params = {})
40
+ return self if new_params.nil? || new_params.empty?
41
+ with_params params.merge(new_params).compact
42
+ end
43
+
44
+ def default_params(defaults = {})
45
+ with_params defaults.merge(params)
46
+ end
47
+
48
+ # @override Seems good to have no-op when params not changed?
49
+ def with_params(new_params)
50
+ if params == new_params
51
+ self
52
+ else
53
+ with_options(params: new_params)
54
+ end
55
+ end
56
+
57
+ def param?(key)
58
+ params.key?(key)
59
+ end
60
+
61
+ # Copies and makes private superclass #response method
62
+ alias_method :__response__, :response
63
+ private :__response__
64
+
65
+ # @override Cache response by default
66
+ def response
67
+ cache.fetch_or_store(:response) { __response__ }
68
+ end
69
+
70
+ # @override
71
+ def each(&block)
72
+ return to_enum unless block_given?
73
+ enumerable_response.each(&block)
74
+ end
75
+
76
+ def enumerable_response
77
+ if options[:enum_on].nil?
78
+ Array.wrap(response)
79
+ else
80
+ keys = Array.wrap options[:enum_on]
81
+ Array.wrap response.dig(*keys)
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def cache
88
+ @cache ||= Concurrent::Map.new
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,53 @@
1
+ module ROM
2
+ module Solr
3
+ class SelectDataset < Dataset
4
+
5
+ config.default_enum_on = [ 'response', 'docs' ]
6
+ config.default_params = { q: '*:*', start: 0, rows: 20, cursorMark: '*', sort: 'id ASC' }
7
+
8
+ # @override
9
+ def each
10
+ while true
11
+ enumerable_response.each { |doc| yield(doc) }
12
+ break if last_page?
13
+ update_cursor_mark
14
+ end
15
+ end
16
+
17
+ def num_found
18
+ response.dig('response', 'numFound')
19
+ end
20
+
21
+ def cursor_mark
22
+ params[:cursorMark]
23
+ end
24
+
25
+ def next_cursor_mark
26
+ response['nextCursorMark']
27
+ end
28
+
29
+ def page_size
30
+ params[:rows]
31
+ end
32
+
33
+ def last_cursor?
34
+ cursor_mark == next_cursor_mark
35
+ end
36
+
37
+ def one_page?
38
+ num_found <= page_size
39
+ end
40
+
41
+ def last_page?
42
+ one_page? || last_cursor?
43
+ end
44
+
45
+ private
46
+
47
+ def update_cursor_mark
48
+ add_params(cursorMark: next_cursor_mark)
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,25 @@
1
+ module ROM
2
+ module Solr
3
+ class Gateway < ROM::HTTP::Gateway
4
+
5
+ adapter :solr
6
+
7
+ def initialize(config = {})
8
+ config[:uri] ||= ENV.fetch('SOLR_URL', 'http://localhost:8983/solr')
9
+ config[:headers] ||= { Accept: 'application/json' }
10
+ super
11
+ end
12
+
13
+ def dataset(name)
14
+ dataset_class(name).new config.merge(base_path: name)
15
+ end
16
+
17
+ def dataset_class(name)
18
+ prefix = name.to_s.split(/_/).map(&:capitalize).join('')
19
+ const_name = "#{prefix}Dataset"
20
+ ROM::Solr.const_defined?(const_name, false) ? ROM::Solr.const_get(const_name, false) : Dataset
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,62 @@
1
+ module ROM
2
+ module Solr
3
+ class PaginatedDataset
4
+
5
+ attr_reader :dataset
6
+
7
+ def initialize(dataset)
8
+ ds = dataset
9
+ .default_params(rows: 20)
10
+ .remove_params(:start)
11
+ .add_params(cursorMark: '*')
12
+
13
+ if ds.param?(:sort)
14
+ unless ds.params[:sort] =~ /\bid\b/
15
+ ds = ds.sort('%{sort},id ASC' % ds.params)
16
+ end
17
+ else
18
+ ds = ds.sort('id ASC')
19
+ end
20
+
21
+ @dataset = ds
22
+ end
23
+
24
+ def each
25
+ while true
26
+ yield dataset
27
+ break if last_page?
28
+ @dataset = dataset.add_params(cursorMark: next_cursor_mark)
29
+ end
30
+ end
31
+
32
+ def cursor_mark
33
+ dataset.params[:cursorMark]
34
+ end
35
+
36
+ def next_cursor_mark
37
+ dataset.response['nextCursorMark']
38
+ end
39
+
40
+ def page_size
41
+ dataset.params[:rows]
42
+ end
43
+
44
+ def total_size
45
+ dataset.num_found
46
+ end
47
+
48
+ def last_cursor?
49
+ cursor_mark == next_cursor_mark
50
+ end
51
+
52
+ def one_page?
53
+ total_size <= page_size
54
+ end
55
+
56
+ def last_page?
57
+ one_page? || last_cursor?
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,25 @@
1
+ module ROM
2
+ module Solr
3
+ class Relation < ROM::HTTP::Relation
4
+ extend Schemaless
5
+
6
+ adapter :solr
7
+
8
+ forward :add_param_values, :default_params, :with_enum_on
9
+
10
+ def fetch(key, default = nil)
11
+ return self if key.nil?
12
+ dataset.response.fetch(key, default)
13
+ end
14
+
15
+ def count
16
+ to_enum.count
17
+ end
18
+
19
+ def all
20
+ self
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,75 @@
1
+ module ROM
2
+ module Solr
3
+ class SchemaRelation < Relation
4
+
5
+ schemaless(:schema, as: :schema_info)
6
+
7
+ # GET /schema
8
+ def info
9
+ fetch('schema')
10
+ end
11
+
12
+ def schema_name
13
+ with_path(:name).fetch(:name)
14
+ end
15
+
16
+ def version
17
+ with_path('version').fetch('version')
18
+ end
19
+
20
+ def unique_key
21
+ with_path('uniquekey').fetch('uniqueKey')
22
+ end
23
+
24
+ def similarity
25
+ with_path('similarity').fetch('similarity')
26
+ end
27
+
28
+ # @param opts [Hash]
29
+ def fields(**opts)
30
+ default_opts = { showDefaults: true }
31
+ with_path('fields')
32
+ .with_enum_on('fields')
33
+ .add_params(default_opts.merge(opts))
34
+ end
35
+
36
+ # @param name [String, Symbol] field name
37
+ # @param opts [Hash]
38
+ def field(name, **opts)
39
+ with_path('fields', name)
40
+ .add_params(opts)
41
+ .fetch('field')
42
+ end
43
+
44
+ # @param opts [Hash]
45
+ def field_types(**opts)
46
+ with_path('fieldtypes')
47
+ .with_enum_on('fieldTypes')
48
+ .add_params(opts)
49
+ end
50
+
51
+ # @param name [String, Symbol] field type name
52
+ # @param opts [Hash]
53
+ def field_type(name, **opts)
54
+ with_path('fieldtypes', name).add_params(opts).fetch('fieldType')
55
+ end
56
+
57
+ # @param opts [Hash]
58
+ def dynamic_fields(**opts)
59
+ with_path('dynamicfields').with_enum_on('dynamicFields').add_params(opts)
60
+ end
61
+
62
+ # @param name [String, Symbol] dynamic field name
63
+ # @param opts [Hash]
64
+ def dynamic_field(name, **opts)
65
+ with_path('dynamicfields', name).add_params(opts).fetch('dynamicField')
66
+ end
67
+
68
+ # @param opts [Hash]
69
+ def copy_fields(**opts)
70
+ with_path('copyfields').with_enum_on('copyFields').add_params(opts)
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,43 @@
1
+ module ROM
2
+ module Solr
3
+ class SelectRelation < Relation
4
+
5
+ schemaless :select, as: :search
6
+
7
+ def filter(*fq)
8
+ add_param_values(:fq, fq)
9
+ end
10
+ alias_method :fq, :filter
11
+
12
+ def query(q)
13
+ add_params(q: q)
14
+ end
15
+ alias_method :q, :query
16
+
17
+ def fields(*fl)
18
+ add_params(fl: fl)
19
+ end
20
+ alias_method :fl, :fields
21
+
22
+ def start(offset)
23
+ add_params(start: offset.to_i)
24
+ end
25
+ alias_method :offset, :start
26
+
27
+ def rows(limit)
28
+ add_params(rows: limit.to_i)
29
+ end
30
+ alias_method :limit, :rows
31
+
32
+ def sort(crit)
33
+ add_params(sort: crit)
34
+ end
35
+
36
+ # @override Don't have to enumerate to get count (may not be exact)
37
+ def count
38
+ dataset.num_found
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ module ROM
2
+ module Solr
3
+ class Request
4
+
5
+ def self.call(dataset)
6
+ uri = URI(dataset.uri)
7
+ uri.query = URI.encode_www_form(dataset.params)
8
+
9
+ http = Net::HTTP.new(uri.host, uri.port)
10
+ http.use_ssl = true if uri.scheme.eql?('https')
11
+
12
+ request_class = Net::HTTP.const_get(ROM::Inflector.classify(dataset.request_method))
13
+ request = request_class.new(uri.request_uri)
14
+
15
+ dataset.headers.each_with_object(request) do |(header, value), request|
16
+ request[header.to_s] = value
17
+ end
18
+
19
+ http.request(request)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ module ROM
2
+ module Solr
3
+ class Response
4
+
5
+ # @return [Hash] Parsed JSON object from Solr response body
6
+ def self.call(response, dataset)
7
+ JSON.parse(response.body)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ module ROM
2
+ module Solr
3
+ class Schema < ROM::HTTP::Schema
4
+
5
+
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ require "hashie"
2
+
3
+ module ROM
4
+ module Solr
5
+ module Schemaless
6
+
7
+ def self.extended(base)
8
+ schemaless_output = Class.new(Hashie::Mash) do
9
+ include Hashie::Extensions::Mash::SymbolizeKeys
10
+ disable_warnings
11
+ end
12
+ base.const_set(:SchemalessOutput, schemaless_output)
13
+ base.option :output_schema, default: ->{ self.class.const_get(:SchemalessOutput) }
14
+ end
15
+
16
+ def schemaless(*args)
17
+ schema(*args) do
18
+ # no schema :)
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -1,32 +1,39 @@
1
1
  require "solrbee/version"
2
- require "solrbee/api_methods"
3
- require "solrbee/query"
4
- require "solrbee/cursor"
5
- require "solrbee/client"
2
+ require "solrbee/array"
3
+ require "rom/solr"
6
4
 
7
5
  module Solrbee
8
6
 
9
- class Error < StandardError; end
7
+ # Factory method
8
+ #
9
+ # @return [ROM::Solr::Gateway] a gateway instance
10
+ def self.gateway
11
+ ROM::Gateway.setup(:solr)
12
+ end
10
13
 
11
- API_VERSION = 'V1'
14
+ # Factory method
15
+ #
16
+ # @return [Solrbee::Documents] a ROM relation for searching
17
+ def self.documents
18
+ container.relations[:search]
19
+ end
12
20
 
13
- # Single-valued field types
14
- STRING = "string"
15
- LONG = "plong"
16
- INT = "pint"
17
- DATE = "pdate"
18
- BOOLEAN = "boolean"
21
+ def self.schema
22
+ container.relations[:schema_info]
23
+ end
19
24
 
20
- # Multi-valued field types
21
- MSTRING = "strings"
22
- MLONG = "plongs"
23
- MINT = "pints"
24
- MDATE = "pdates"
25
- MBOOLEAN = "booleans"
25
+ # @return [ROM::Configuration] configuration
26
+ def self.config
27
+ @config ||= ROM::Configuration.new(:solr) do |config|
28
+ config.register_relation(
29
+ ROM::Solr::SelectRelation,
30
+ ROM::Solr::SchemaRelation
31
+ )
32
+ end
33
+ end
26
34
 
27
- # Base URL
28
- def self.solr_url
29
- ENV.fetch('SOLR_URL', 'http://localhost:8983/solr').sub(/\/\z/, '')
35
+ def self.container
36
+ ROM.container(config)
30
37
  end
31
38
 
32
39
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Solrbee
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
 
25
25
  spec.add_dependency "hashie"
26
+ spec.add_dependency "rom"
27
+ spec.add_dependency "rom-http"
26
28
 
27
29
  spec.add_development_dependency "bundler"
28
30
  spec.add_development_dependency "rake"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solrbee
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.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-14 00:00:00.000000000 Z
11
+ date: 2020-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rom
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rom-http
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: bundler
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -96,11 +124,21 @@ files:
96
124
  - Rakefile
97
125
  - bin/console
98
126
  - bin/setup
127
+ - config/api.yml
128
+ - lib/rom/solr.rb
129
+ - lib/rom/solr/dataset.rb
130
+ - lib/rom/solr/datasets/select_dataset.rb
131
+ - lib/rom/solr/gateway.rb
132
+ - lib/rom/solr/paginated_dataset.rb
133
+ - lib/rom/solr/relation.rb
134
+ - lib/rom/solr/relations/schema_relation.rb
135
+ - lib/rom/solr/relations/select_relation.rb
136
+ - lib/rom/solr/request.rb
137
+ - lib/rom/solr/response.rb
138
+ - lib/rom/solr/schema.rb
139
+ - lib/rom/solr/schemaless.rb
99
140
  - lib/solrbee.rb
100
- - lib/solrbee/api_methods.rb
101
- - lib/solrbee/client.rb
102
- - lib/solrbee/cursor.rb
103
- - lib/solrbee/query.rb
141
+ - lib/solrbee/array.rb
104
142
  - lib/solrbee/version.rb
105
143
  - solrbee.gemspec
106
144
  homepage: https://github.com/dchandekstark/solrbee
@@ -1,94 +0,0 @@
1
- module Solrbee
2
- module ApiMethods
3
-
4
- def ping
5
- response = request(path: '/admin/ping')
6
- response['status']
7
- end
8
-
9
- def schema
10
- response = request(path: '/schema')
11
- response['schema']
12
- end
13
-
14
- def schema_name
15
- response = request(path: '/schema/name')
16
- response['name']
17
- end
18
-
19
- def schema_version
20
- response = request(path: '/schema/version')
21
- response['version']
22
- end
23
-
24
- def fields(**params)
25
- response = request(path: '/schema/fields', params: params)
26
- response['fields']
27
- end
28
-
29
- def field(field_name, **params)
30
- response = request(path: '/schema/fields/%s' % field_name, params: params)
31
- response['field']
32
- end
33
-
34
- def unique_key
35
- response = request(path: '/schema/uniquekey')
36
- response['uniqueKey']
37
- end
38
-
39
- def field_types(**params)
40
- response = request(path: '/schema/fieldtypes', params: params)
41
- response['fieldTypes']
42
- end
43
-
44
- def field_type(field_name, **params)
45
- response = request(path: '/schema/fieldtypes/%s' % field_name, params: params)
46
- response['fieldType']
47
- end
48
-
49
- def field_names
50
- fields.map { |f| f['name'] }
51
- end
52
-
53
- def field_type_names
54
- field_types.map { |f| f['name'] }
55
- end
56
-
57
- def modify_schema(commands)
58
- request(path: '/schema', data: commands)
59
- end
60
-
61
- def add_field(field)
62
- modify_schema("add-field"=>field)
63
- end
64
-
65
- def delete_field(field_name)
66
- modify_schema("delete-field"=>{"name"=>field_name})
67
- end
68
-
69
- def replace_field(field)
70
- modify_schema("replace-field"=>field)
71
- end
72
-
73
- # "real-time get"
74
- def get_by_id(*ids, **params)
75
- response = request(path: '/get', params: params.merge(id: ids.join(',')))
76
- response['response']['doc'] || response['response']['docs']
77
- end
78
-
79
- def index(*docs, **params)
80
- request(path: '/update/json/docs', data: docs, params: params)
81
- end
82
- alias_method :add, :index
83
- alias_method :update, :index
84
-
85
- def delete(*ids)
86
- request(path: '/update', data: { delete: ids })
87
- end
88
-
89
- def query(**params)
90
- request(path: '/query', data: params)
91
- end
92
-
93
- end
94
- end
@@ -1,50 +0,0 @@
1
- require "net/http"
2
- require "uri"
3
- require "json"
4
-
5
- module Solrbee
6
- class Client
7
- include ApiMethods
8
-
9
- attr_reader :uri
10
-
11
- def self.cursor(url: nil)
12
- new(url: url).cursor
13
- end
14
-
15
- def initialize(url: nil)
16
- @uri = URI(url || ENV['SOLR_URL'])
17
- end
18
-
19
- def connection
20
- Net::HTTP.new(uri.host, uri.port).tap do |http|
21
- http.use_ssl = true if uri.scheme == 'https'
22
- end
23
- end
24
-
25
- def cursor
26
- Cursor.new(self)
27
- end
28
-
29
- def request(path:, data: nil, params: {})
30
- req_class = data ? Net::HTTP::Post : Net::HTTP::Get
31
-
32
- req_uri = uri.dup.tap do |u|
33
- u.path += path
34
- u.query = URI.encode_www_form(params) unless params.empty?
35
- end
36
-
37
- req = req_class.new(req_uri)
38
- req['Accept'] = 'application/json'
39
-
40
- if data
41
- req['Content-Type'] = 'application/json'
42
- req.body = JSON.dump(data)
43
- end
44
-
45
- http_response = connection.request(req)
46
- JSON.parse(http_response.body)
47
- end
48
-
49
- end
50
- end
@@ -1,37 +0,0 @@
1
- module Solrbee
2
- #
3
- # SUMMARY
4
- #
5
- # > client = Solrbee::Client.new
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['response']['numFound'] == 0
29
- break if response['nextCursorMark'] == q.params.cursorMark
30
- response['response']['docs'].each { |doc| yielder << doc }
31
- q.params.cursorMark = response['nextCursorMark']
32
- end
33
- end
34
- end
35
-
36
- end
37
- end
@@ -1,35 +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
- property :query, from: :q, default: '*:*'
9
- property :filter, from: :fq
10
- property :limit, from: :rows, default: 10
11
- property :fields, from: :fl
12
- property :sort
13
- property :offset, from: :start
14
- property :facet
15
- property :queries
16
- property :params, default: {}
17
-
18
- # Build a query for a Cursor
19
- def self.cursor(params, unique_key)
20
- Query.new(params).tap do |q|
21
- q.delete(:offset) # incompatible with cursor
22
- q.params[:cursorMark] = '*' # initial cursor mark
23
-
24
- # Sort on unique key is required for cursor
25
- q.sort = "#{unique_key} ASC" unless q.sort
26
- unless q.sort =~ /\b#{unique_key}\b/
27
- clauses = q.sort.split(/,/)
28
- clauses << "#{unique_key} ASC"
29
- q.sort = clauses.join(',')
30
- end
31
- end
32
- end
33
-
34
- end
35
- end