neo4apis 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +16 -0
- data/README.md +73 -0
- data/lib/neo4apis/base.rb +82 -0
- data/lib/neo4apis/query_buffer.rb +51 -0
- data/lib/neo4apis/version.rb +3 -0
- data/lib/neo4apis.rb +6 -0
- data/neo4apis.gemspec +26 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 30ba847cad3af0957ed3e603dd236b5037c80f20
|
4
|
+
data.tar.gz: eb86312649a77abe55ae3c668b178709cb5ac803
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1ac9fcb8bbe6b8f1f934df3f81ad6dbeb267fcc502bff457fe3b7a6698963d0de9dff9f51874f1f0125585c1ee62af9975384b3ad3231832ae882d4c5fbfdf7c
|
7
|
+
data.tar.gz: bd4597cad7cf2adf0a6c4dab7e2235e6ce3b7c86b45b30f1e07fa564179fbc0930eda0c6134b67ed30553c64bebce29fd9edc3c9b2d8eee78d1fb8a7b5aa6758
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
neo4apis is a ruby gem for building gems which import data into neo4j. Takes care of batching of queries for better import performance
|
3
|
+
|
4
|
+
In the below example we assume that a variable `awesome_client` is passed in which allows us to make requests to the API. This may be, for example, provided by another gem.
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
require 'neo4apis'
|
8
|
+
|
9
|
+
module Neo4Apis
|
10
|
+
class AwesomeSite < Base
|
11
|
+
PREFIX = 'awesome_site'
|
12
|
+
|
13
|
+
def initialize(neo4j_client, options = {})
|
14
|
+
@client = options[:awesome_client]
|
15
|
+
|
16
|
+
options[:uuids] = (options[:uuids] || {}).merge({
|
17
|
+
User: :id,
|
18
|
+
Widget: :uuid
|
19
|
+
})
|
20
|
+
|
21
|
+
super(neo4j_client, options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def import_widget_search(*args)
|
25
|
+
@client.widget_search(*args).each do |widget|
|
26
|
+
add_widget(widget)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def add_widget(widget)
|
33
|
+
user_node = add_user(widget.owner)
|
34
|
+
|
35
|
+
# add_node comes from From Neo4Apis::Base
|
36
|
+
node = add_node :Widget, {
|
37
|
+
uuid: widget.uuid,
|
38
|
+
text: widget.text,
|
39
|
+
}
|
40
|
+
|
41
|
+
# add_relationship comes from Neo4Apis::Base
|
42
|
+
add_relationship(:owns, user_node, node)
|
43
|
+
|
44
|
+
node
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_user(user)
|
48
|
+
add_node :User, {
|
49
|
+
id: user.id,
|
50
|
+
username: user.username,
|
51
|
+
name: user.name,
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
Then somebody else could use your gem in the following manner:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
|
63
|
+
neo4j_session = Neo4j::Session.open # From the neo4j-core gem
|
64
|
+
awesome_client = Awesome.open # From a theoretical API wrapping gem
|
65
|
+
|
66
|
+
neo4apis_awesome = Neo4Apis::AwesomeSite.new(neo4j_session, awesome_client: awesome_client)
|
67
|
+
|
68
|
+
neo4apis_awesome.batch do
|
69
|
+
neo4apis_awesome.import_widget_search('cool') # Does a search for 'cool' via the Awesome gem and imports to the neo4j database
|
70
|
+
end
|
71
|
+
|
72
|
+
```
|
73
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Neo4Apis
|
2
|
+
class Base
|
3
|
+
DEFAULT_FLUSH_SIZE = 500
|
4
|
+
|
5
|
+
NODE_PROXIES = {}
|
6
|
+
|
7
|
+
def initialize(neo4j_session, options = {})
|
8
|
+
@buffer = QueryBuffer.new(neo4j_session)
|
9
|
+
@flush_size = DEFAULT_FLUSH_SIZE
|
10
|
+
(options[:uuids] || {}).each do |label, uuid_field|
|
11
|
+
NODE_PROXIES[label] = Struct.new(:label, :props) do
|
12
|
+
const_set(:UUID_FIELD, uuid_field)
|
13
|
+
|
14
|
+
def uuid_value
|
15
|
+
raise ArgumentError, "props does not have UUID field `#{uuid_field}` for #{self.inspect}" if not props.has_key?(uuid_field)
|
16
|
+
|
17
|
+
props[uuid_field]
|
18
|
+
end
|
19
|
+
|
20
|
+
def uuid_field
|
21
|
+
self.class::UUID_FIELD
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_node(label, props = {})
|
28
|
+
require_batch
|
29
|
+
|
30
|
+
node_proxy = NODE_PROXIES[label]
|
31
|
+
raise ArgumentError, "No UUID specified for label `#{label}`" if not node_proxy
|
32
|
+
|
33
|
+
node_proxy.new(label, props).tap do |node_proxy|
|
34
|
+
@buffer << create_node_query(node_proxy)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_relationship(type, source, target, props = {})
|
39
|
+
raise ArgumentError, "No source specified" if not source
|
40
|
+
raise ArgumentError, "No target specified" if not target
|
41
|
+
|
42
|
+
require_batch
|
43
|
+
|
44
|
+
@buffer << create_relationship_query(type, source, target, props)
|
45
|
+
end
|
46
|
+
|
47
|
+
def batch
|
48
|
+
@in_batch = true
|
49
|
+
|
50
|
+
yield
|
51
|
+
|
52
|
+
@buffer.flush
|
53
|
+
ensure
|
54
|
+
@in_batch = false
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def create_node_query(node_proxy)
|
60
|
+
Neo4j::Core::Query.new.
|
61
|
+
merge(node: {node_proxy.label => {node_proxy.uuid_field => node_proxy.uuid_value}}).
|
62
|
+
on_create_set(node: node_proxy.props)
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_relationship_query(type, source, target, props)
|
66
|
+
Neo4j::Core::Query.new.
|
67
|
+
match(source: {source.label => {source.uuid_field => source.uuid_value}}).
|
68
|
+
match(target: {target.label => {target.uuid_field => target.uuid_value}}).
|
69
|
+
merge("source-[:#{type}]->target")
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_to_buffer(*args)
|
73
|
+
flush_buffer if buffer.size >= FLUSH_SIZE
|
74
|
+
|
75
|
+
@buffer << args
|
76
|
+
end
|
77
|
+
|
78
|
+
def require_batch
|
79
|
+
raise "Must be in a batch" if not @in_batch
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Neo4Apis
|
2
|
+
class QueryBuffer < Array
|
3
|
+
|
4
|
+
def initialize(neo4j_session)
|
5
|
+
@neo4j_session = neo4j_session
|
6
|
+
|
7
|
+
uri = URI.parse(@neo4j_session.resource_url)
|
8
|
+
|
9
|
+
@faraday_connection = Faraday.new(:url => "#{uri.scheme}://#{uri.host}:#{uri.port}") do |faraday|
|
10
|
+
faraday.request :url_encoded # form-encode POST params
|
11
|
+
faraday.response :logger # log requests to STDOUT
|
12
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
13
|
+
end
|
14
|
+
|
15
|
+
super()
|
16
|
+
end
|
17
|
+
|
18
|
+
def flush
|
19
|
+
execute
|
20
|
+
|
21
|
+
clear
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def execute
|
28
|
+
puts "request_body_data", request_body_data.inspect
|
29
|
+
@faraday_connection.post do |req|
|
30
|
+
req.url '/db/data/transaction/commit'
|
31
|
+
req.headers['Accept'] = 'application/json; charset=UTF-8'
|
32
|
+
req.headers['Content-Type'] = 'application/json'
|
33
|
+
req.headers['X-Stream'] = 'true'
|
34
|
+
req.body = request_body_data.to_json
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def request_body_data
|
39
|
+
{
|
40
|
+
statements: self.map do |query|
|
41
|
+
{
|
42
|
+
statement: query.to_cypher,
|
43
|
+
parameters: query.send(:merge_params)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
data/lib/neo4apis.rb
ADDED
data/neo4apis.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
lib = File.expand_path('../lib/', __FILE__)
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
3
|
+
|
4
|
+
require 'neo4apis/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "neo4apis"
|
8
|
+
s.version = Neo4Apis::VERSION
|
9
|
+
s.required_ruby_version = ">= 1.9.1"
|
10
|
+
|
11
|
+
s.authors = "Brian Underwood"
|
12
|
+
s.email = 'public@brian-underwood.codes'
|
13
|
+
s.homepage = "https://github.com/neo4jrb/neo4apis/"
|
14
|
+
s.summary = "An API to import web API data to neo4j"
|
15
|
+
s.license = 'MIT'
|
16
|
+
s.description = <<-EOF
|
17
|
+
A core library for importing data from APIs into neo4j. Designed to be used with an adapter
|
18
|
+
EOF
|
19
|
+
|
20
|
+
s.require_path = 'lib'
|
21
|
+
s.files = Dir.glob("{bin,lib,config}/**/*") + %w(README.md Gemfile neo4apis.gemspec)
|
22
|
+
|
23
|
+
s.add_dependency('faraday', "~> 0.9.0")
|
24
|
+
s.add_dependency("neo4j-core", "~> 3.0.3")
|
25
|
+
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: neo4apis
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brian Underwood
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.9.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.9.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: neo4j-core
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.3
|
41
|
+
description: |
|
42
|
+
A core library for importing data from APIs into neo4j. Designed to be used with an adapter
|
43
|
+
email: public@brian-underwood.codes
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- Gemfile
|
49
|
+
- README.md
|
50
|
+
- lib/neo4apis.rb
|
51
|
+
- lib/neo4apis/base.rb
|
52
|
+
- lib/neo4apis/query_buffer.rb
|
53
|
+
- lib/neo4apis/version.rb
|
54
|
+
- neo4apis.gemspec
|
55
|
+
homepage: https://github.com/neo4jrb/neo4apis/
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 1.9.1
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.2.2
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: An API to import web API data to neo4j
|
79
|
+
test_files: []
|