neo4apis 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'neo4j-core', '~> 3.0.0', path: '/Users/brian/github/neo4jrb/neo4j-core'
6
+
7
+ gem 'twitter'
8
+
9
+ group :development do
10
+ gem 'pry'
11
+ end
12
+
13
+ group :test do
14
+ gem 'rspec'
15
+ end
16
+
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
+
@@ -0,0 +1,3 @@
1
+ module Neo4Apis
2
+ VERSION = '0.0.1'
3
+ end
data/lib/neo4apis.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'neo4j-core'
2
+
3
+ require 'neo4apis/version'
4
+
5
+ require 'neo4apis/query_buffer'
6
+ require 'neo4apis/base'
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: []