solrbee 0.1.0 → 0.1.1

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: ca8f6d8f901268390057453075d0c39306b2362cb1216ec4dbcdb168b6d5bb18
4
- data.tar.gz: b17d0b604e4276a47c2e54d17fc92f9b9cc173fb1c2b283cc4d15f6f506c99d8
3
+ metadata.gz: 77127390eb03bfbd53eec6916f7873fab49b6436f4acb94c528f2cec7ed5f76b
4
+ data.tar.gz: '08ab2300881e0fdacaafa0007d1a17031a2b11bebfe2ade9cbf533a02a7b2b42'
5
5
  SHA512:
6
- metadata.gz: 3967982e1454c5659be6716eaf2e3a1a215046b6c3bfbe383c09810b519391017ddb4febedc861235d97b44253fd4950ad75f88dbcddc5378e33d5e37d822c59
7
- data.tar.gz: 9cd90db400ec1a2ec23daa227e6e22afb23da39328fb66384bd2cf18c52a01ee4c5db1f2620079a4a63d19096edc706de5320be3e93e67f8da5c2fb600948c61
6
+ metadata.gz: 5642a45f1013a4ddf33f4a339f0990ec218d7c3ebce3e6b3e1a0811c81256a6c155df333d7894618de9cb4a8b9e7c9eac5f178237474e96cd2de5ec7193cee83
7
+ data.tar.gz: bba5257728a581433cf72dbd4dce18ab5f8f7baea95afca7dca75c16f5fc17b509110c9e8ecb9a87713960f3eccf951d0bf11a0afe8b4ba01de2f331fcefd095
data/Makefile CHANGED
@@ -2,6 +2,13 @@ SHELL = /bin/bash
2
2
 
3
3
  .PHONY : test
4
4
  test:
5
- docker run --rm -d --name solrbee-test solr:8 solr-precreate solrbee
6
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:
7
14
  docker stop solrbee-test
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # Solrbee
2
2
 
3
+ ![Bee photo (c) David Chandek-Stark](https://raw.githubusercontent.com/dchandekstark/images/main/solrbee.jpg)
4
+
3
5
  Solrbee is intended as a lightweight library for interacting with a modern Solr instance
4
- using a managed schema. Our intestest is primarily in using Solr as data store, for example,
5
- as an alterative to an RDBMS.
6
+ as NoSQL data store.
7
+
8
+ We are currently building on the JSON APIs (V1).
6
9
 
7
10
  ## Installation
8
11
 
@@ -1,14 +1,12 @@
1
- require "net/http"
2
- require "uri"
3
- require "json"
4
-
5
1
  require "solrbee/version"
6
- require "solrbee/base"
7
2
  require "solrbee/response"
8
- require "solrbee/collection"
9
- require "solrbee/schema_api"
3
+ require "solrbee/request_params"
4
+ require "solrbee/query"
5
+ require "solrbee/client"
6
+ require "solrbee/cursor"
10
7
 
11
8
  module Solrbee
9
+
12
10
  class Error < StandardError; end
13
11
 
14
12
  # Single-valued field types
@@ -25,41 +23,9 @@ module Solrbee
25
23
  MDATE = "pdates"
26
24
  MBOOLEAN = "booleans"
27
25
 
26
+ # Base URL
28
27
  def self.solr_url
29
- ENV.fetch('SOLR_URL', 'http://localhost:8983/solr/')
30
- end
31
-
32
- def self.solr_uri
33
- URI(solr_url)
34
- end
35
-
36
- def self.connection
37
- Net::HTTP.new(solr_uri.host, solr_uri.port).tap do |http|
38
- http.use_ssl = true if solr_uri.scheme == 'https'
39
- end
40
- end
41
-
42
- def self.request_class(method)
43
- Net::HTTP.const_get(method.to_s.downcase.capitalize)
44
- end
45
-
46
- def self.request(method, path)
47
- u = URI.join(solr_url, path)
48
- req = request_class(method).new(u, {'Accept'=>'application/json'})
49
- yield req if block_given?
50
- res = connection.request(req)
51
- Response.handle(res)
52
- end
53
-
54
- def self.get(path)
55
- request(:get, path)
56
- end
57
-
58
- def self.post(path, data)
59
- request(:post, path) do |req|
60
- req['Content-Type'] = 'application/json'
61
- req.body = JSON.dump(data)
62
- end
28
+ ENV.fetch('SOLR_URL', 'http://localhost:8983/solr').sub(/\/\z/, '')
63
29
  end
64
30
 
65
31
  end
@@ -0,0 +1,85 @@
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
@@ -0,0 +1,59 @@
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
@@ -0,0 +1,37 @@
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
@@ -0,0 +1,36 @@
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
@@ -0,0 +1,13 @@
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,21 +1,24 @@
1
+ require 'hashie'
2
+
1
3
  module Solrbee
2
- class Response < Base
4
+ class Response < Hashie::Mash
5
+
6
+ disable_warnings
3
7
 
4
- coerce_key :schema, Schema
5
- coerce_key :fields, Array[Field]
6
- coerce_key :field, Field
7
- coerce_key :responseHeader, Header
8
- coerce_key :fieldTypes, Array[FieldType]
9
- coerce_key :fieldType, FieldType
8
+ def header
9
+ responseHeader
10
+ end
11
+
12
+ def num_found
13
+ response.numFound
14
+ end
10
15
 
11
- def self.handle(http_response)
12
- http_response.value # raises Net::HTTPServerException
13
- parsed = JSON.parse(http_response.body, symbolize_names: true, object_class: Solrbee::Base)
14
- new(parsed)
16
+ def docs
17
+ response.docs
15
18
  end
16
19
 
17
- def status
18
- responseHeader.status
20
+ def doc
21
+ response.doc
19
22
  end
20
23
 
21
24
  end
@@ -1,3 +1,3 @@
1
1
  module Solrbee
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
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.1.0
4
+ version: 0.1.1
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-02 00:00:00.000000000 Z
11
+ date: 2020-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -97,10 +97,12 @@ files:
97
97
  - bin/console
98
98
  - bin/setup
99
99
  - lib/solrbee.rb
100
- - lib/solrbee/base.rb
101
- - lib/solrbee/collection.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
102
105
  - lib/solrbee/response.rb
103
- - lib/solrbee/schema_api.rb
104
106
  - lib/solrbee/version.rb
105
107
  - solrbee.gemspec
106
108
  homepage: https://github.com/dchandekstark/solrbee
@@ -1,14 +0,0 @@
1
- require 'hashie'
2
-
3
- module Solrbee
4
- class Base < Hashie::Hash
5
- include Hashie::Extensions::Coercion
6
- include Hashie::Extensions::MergeInitializer
7
- include Hashie::Extensions::MethodAccess
8
- end
9
-
10
- Field = Class.new(Base)
11
- FieldType = Class.new(Base)
12
- Header = Class.new(Base)
13
- Schema = Class.new(Base)
14
- end
@@ -1,19 +0,0 @@
1
- module Solrbee
2
- class Collection
3
-
4
- attr_reader :name
5
-
6
- def initialize(name)
7
- @name = name
8
- end
9
-
10
- def to_s
11
- name
12
- end
13
-
14
- def schema
15
- @schema ||= SchemaApi.new(self)
16
- end
17
-
18
- end
19
- end
@@ -1,86 +0,0 @@
1
- module Solrbee
2
- class SchemaApi
3
-
4
- attr_reader :collection
5
-
6
- def initialize(collection)
7
- @collection = collection
8
- end
9
-
10
- def to_h
11
- content
12
- end
13
-
14
- def name
15
- response = Solrbee.get('%s/schema/name' % collection)
16
- response.name
17
- end
18
-
19
- def version
20
- response = Solrbee.get('%s/schema/version' % collection)
21
- response.version
22
- end
23
-
24
- def content
25
- response = Solrbee.get('%s/schema' % collection)
26
- response.schema
27
- end
28
-
29
- def fields(show_defaults: true)
30
- response = Solrbee.get('%s/schema/fields?showDefaults=%s' % [collection, show_defaults])
31
- response.fields
32
- end
33
-
34
- def field(field_name, show_defaults: true)
35
- response = Solrbee.get('%s/schema/fields/%s?showDefaults=%s' % [collection, field_name, show_defaults])
36
- response.field
37
- end
38
-
39
- def unique_key
40
- response = Solrbee.get('%s/schema/uniquekey' % collection)
41
- response.uniqueKey
42
- end
43
-
44
- def field_types(show_defaults: true)
45
- response = Solrbee.get('%s/schema/fieldtypes?showDefaults=%s' % [collection, show_defaults])
46
- response.fieldTypes
47
- end
48
-
49
- def field_type(field_name, show_defaults: true)
50
- response = Solrbee.get('%s/schema/fieldtypes/%s?showDefaults=%s' % [collection, field_name, show_defaults])
51
- response.fieldType
52
- end
53
-
54
- def field_names
55
- fields.map(&:name)
56
- end
57
-
58
- def field_type_names
59
- field_types.map(&:name)
60
- end
61
-
62
- def index(*docs, commit: true)
63
- Solrbee.post('%s/update/json/docs?commit=%s' % [collection, commit], docs)
64
- end
65
-
66
- def add_field(field)
67
- data = { "add-field" => field }
68
- Solrbee.post('%s/schema' % collection, data)
69
- end
70
-
71
- def delete_field(field)
72
- data = {
73
- "delete-field" => {
74
- "name" => field.name
75
- }
76
- }
77
- Solrbee.post('%s/schema' % collection, data)
78
- end
79
-
80
- def replace_field(field)
81
- data = { "replace-field" => field }
82
- Solrbee.post('%s/schema' % collection, data)
83
- end
84
-
85
- end
86
- end