neo4j_bolt 0.1.7 → 0.1.9

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: 86471d4b049b4054a378f5084ae13dda181bd818a205ee4a67e6aa4bc5d0607f
4
- data.tar.gz: b1e855e4689946026eaa7971acb730577a57973b02605c893916d15e2438b1f3
3
+ metadata.gz: 164a75bd36d3c0f815786385b8e4a01f47f4d43177ea69966bd513d657167512
4
+ data.tar.gz: b0426c90bb254857bc7d19ef97019554145befa1f022c1134f992021f7b19609
5
5
  SHA512:
6
- metadata.gz: e4e414cb24861f58ae67f2a5c92da46f720c861fd49131befa16a9c046ea557d1e31fb40130fe892aa91b38d0ec3de881d4da94de4fde4a5288ab0add379c33f
7
- data.tar.gz: be8ed37b6ea0a7e358c25257eea3be90f78c2fd1342a4666bc244a5a379e241780a6df01d4005c4b26a4986a2fd24cd0a65f7569f4de19bcbf4a65517a33aa8a
6
+ metadata.gz: d8b2ab2893a70abcf2cc8ca61d88dfb31cbd6bb6cb71cd250c4863ec71c9efdbedc15db03919ac83e99cb03b194dd74d55b70ae94bb9701a3295506cc3943b9d
7
+ data.tar.gz: 7e61cc6b852447a14175ec463bc8504dfa81bc021c664b5eccf0467577e87efd43e03d3bb001faa40401f0441b7cd6a6ead23a24ce75bd9b2ab0c6aacc64bd68
data/Gemfile CHANGED
@@ -5,3 +5,4 @@ gemspec
5
5
 
6
6
  gem "rake", "~> 12.0"
7
7
  gem "rspec", "~> 3.0"
8
+ gem "gli"
data/Gemfile.lock CHANGED
@@ -1,12 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- neo4j_bolt (0.1.6)
4
+ neo4j_bolt (0.1.8)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  diff-lcs (1.5.0)
10
+ gli (2.21.0)
10
11
  rake (12.3.3)
11
12
  rspec (3.11.0)
12
13
  rspec-core (~> 3.11.0)
@@ -26,6 +27,7 @@ PLATFORMS
26
27
  ruby
27
28
 
28
29
  DEPENDENCIES
30
+ gli
29
31
  neo4j_bolt!
30
32
  rake (~> 12.0)
31
33
  rspec (~> 3.0)
data/bin/neo4j_bolt ADDED
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require "neo4j_bolt"
5
+ rescue LoadError
6
+ require "bundler/setup"
7
+ require "neo4j_bolt"
8
+ end
9
+ require "gli"
10
+
11
+ include Neo4jBolt
12
+
13
+ class App
14
+ extend GLI::App
15
+
16
+ program_desc 'run various Neo4j housekeeping tasks'
17
+ version Neo4jBolt::VERSION
18
+
19
+ flag [:v, :verbosity], :default_value => 0
20
+ flag [:h, :host], :default_value => 'localhost:7687'
21
+
22
+ pre do |global_options, command, options, args|
23
+ host = global_options[:host]
24
+ Neo4jBolt.bolt_host = host.split(':').first
25
+ Neo4jBolt.bolt_port = host.split(':').last.to_i
26
+ Neo4jBolt.bolt_verbosity = global_options[:verbosity].to_i
27
+ true
28
+ end
29
+
30
+ # --------------------------------------------
31
+
32
+ desc 'Console'
33
+ command :console do |c|
34
+ c.action do
35
+ require "irb"
36
+ IRB.start(__FILE__)
37
+ end
38
+ end
39
+
40
+ # --------------------------------------------
41
+
42
+ desc 'Dump database'
43
+ long_desc 'Dump all nodes and relationships.'
44
+ command :dump do |c|
45
+ c.flag [:o, :out_file], :default_value => '/dev/stdout'
46
+ c.action do |global_options, options|
47
+ File.open(options[:out_file], 'w') do |f|
48
+ dump_database(f)
49
+ end
50
+ end
51
+ end
52
+
53
+ # --------------------------------------------
54
+
55
+ desc 'Load database dump'
56
+ long_desc 'Load nodes and relationships from a database dump.'
57
+ command :load do |c|
58
+ # c.flag [:i, :in_file], :desc => 'input path', :required => true
59
+ c.switch [:f, :force], :default_value => false, :desc => 'force appending nodes even if the database is not empty'
60
+ c.action do |global_options, options, args|
61
+ help_now!('input path is required') if args.empty?
62
+ path = args.shift
63
+ File.open(path, 'r') do |f|
64
+ load_database_dump(f, force_append: options[:force])
65
+ end
66
+ end
67
+ end
68
+
69
+ # --------------------------------------------
70
+
71
+ desc 'Clear database'
72
+ long_desc 'Clear all nodes and relationships'
73
+ command :clear do |c|
74
+ c.switch [:srsly], :required => true, :negatable => false, :desc => 'Specify --srsly to really clear the database'
75
+ c.action do |global_options, options, args|
76
+ if options[:srsly]
77
+ neo4j_query("MATCH (n) DETACH DELETE n;")
78
+ else
79
+ STDERR.puts "Doing nothing unless you specify --srsly."
80
+ end
81
+ end
82
+ end
83
+
84
+ # --------------------------------------------
85
+
86
+ desc 'Visualize database'
87
+ long_desc 'Generate a GraphViz-formatted visual representation of the database'
88
+ command :visualize do |c|
89
+ c.flag [:o, :out_file], :default_value => '/dev/stdout'
90
+ c.switch [:p, :properties], :default_value => false, :desc => 'include properties'
91
+ c.action do |global_options, options|
92
+ File.open(options[:out_file], 'w') do |f|
93
+ all_labels = Set.new()
94
+
95
+ TR = {'String' => 'string',
96
+ 'Array' => 'list',
97
+ 'Hash' => 'hash',
98
+ 'TrueClass' => 'true',
99
+ 'FalseClass' => 'false',
100
+ 'NilClass' => 'null',
101
+ 'Integer' => 'int',
102
+ 'Float' => 'float'
103
+ }
104
+
105
+ neo4j_query("MATCH (n) RETURN DISTINCT labels(n) AS labels") do |entry|
106
+ labels = entry['labels']
107
+ if labels.size != 1
108
+ raise "multiple labels per node not supported yet: #{labels.join(' ')}"
109
+ end
110
+ all_labels << labels.first
111
+ end
112
+
113
+ all_relationships = Set.new()
114
+
115
+ neo4j_query("MATCH (a)-[r]->(b) RETURN DISTINCT labels(a) AS la, type(r) AS t, labels(b) AS lb;") do |entry|
116
+ la = entry['la'].first
117
+ t = entry['t']
118
+ lb = entry['lb'].first
119
+ all_relationships << "#{la}/#{t}/#{lb}"
120
+ end
121
+
122
+ properties_for_label = {}
123
+ counts_for_label = {}
124
+
125
+ all_labels.to_a.sort.each do |label|
126
+ properties_for_label[label] ||= {}
127
+ if options[:properties]
128
+ neo4j_query("MATCH (n:#{label}) RETURN n") do |entry|
129
+ counts_for_label[label] ||= 0
130
+ counts_for_label[label] += 1
131
+ node = entry['n']
132
+ node.each_pair do |key, value|
133
+ properties_for_label[label][key] ||= {:classes => Set.new()}
134
+ properties_for_label[label][key][:classes] << value.class
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ all_relationships.each do |s|
141
+ properties_for_label[s] ||= {}
142
+ parts = s.split('/')
143
+ la = parts[0]
144
+ type = parts[1]
145
+ lb = parts[2]
146
+ if options[:properties]
147
+ neo4j_query("MATCH (a:#{la})-[r:#{type}]->(b:#{lb}) RETURN r") do |entry|
148
+ counts_for_label[s] ||= 0
149
+ counts_for_label[s] += 1
150
+ rel = entry['r']
151
+ rel.each_pair do |key, value|
152
+ properties_for_label[s][key] ||= {:classes => Set.new()}
153
+ properties_for_label[s][key][:classes] << value.class
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ dot = StringIO.open do |io|
160
+ io.puts "digraph {"
161
+ io.puts "graph [fontname = Helvetica, fontsize = 10, nodesep = 0.2, ranksep = 0.3];"
162
+ io.puts "node [fontname = Helvetica, fontsize = 10, shape = none, margin = 0];"
163
+ io.puts "edge [fontname = Helvetica, fontsize = 10, arrowsize = 0.6, color = \"#000000\"];"
164
+ io.puts 'rankdir=LR;'
165
+ io.puts 'splines=true;'
166
+ properties_for_label.keys.sort.each do |lbl|
167
+ label = "<<table valign='top' align='left' border='0' cellborder='0' cellspacing='0' cellpadding='4'>"
168
+ label += "<tr><td border='1' bgcolor='#fce94f' valign='top' align='left' colspan='2'><b>#{lbl}</b>"
169
+ if options[:properties]
170
+ label += " <i>(#{counts_for_label[lbl]})</i>"
171
+ end
172
+ label += "</td></tr>"
173
+ properties_for_label[lbl].keys.sort.each do |key|
174
+ label += "<tr>"
175
+ label += "<td border='1' valign='top' align='left' colspan='1'>#{key}</td>"
176
+ label += "<td border='1' valign='top' align='left' colspan='1'>#{properties_for_label[lbl][key][:classes].to_a.map { |x| TR[x.to_s] || x.to_s }.sort.join(' / ')}</td>"
177
+ label += "</tr>"
178
+ end
179
+ label += "</table>>"
180
+ io.puts "\"#{lbl}\" [label = #{label}, pencolor = \"#000000\"];"
181
+ end
182
+ all_relationships.each do |s|
183
+ parts = s.split('/')
184
+ la = parts[0]
185
+ type = parts[1]
186
+ lb = parts[2]
187
+
188
+ label = "<<table valign='top' align='left' border='0' cellborder='0' cellspacing='0' cellpadding='4'>"
189
+ label += "<tr><td border='1' bgcolor='#d3d7cf' valign='top' align='left' colspan='2'><b>#{type}</b>"
190
+ if options[:properties]
191
+ label += " <i>(#{counts_for_label[s]})</i>"
192
+ end
193
+ label += "</td></tr>"
194
+ (properties_for_label[s] || {}).keys.sort.each do |key|
195
+ label += "<tr>"
196
+ label += "<td border='1' valign='top' align='left' colspan='1'>#{key}</td>"
197
+ label += "<td border='1' valign='top' align='left' colspan='1'>#{properties_for_label[s][key][:classes].to_a.map { |x| TR[x.to_s] || x.to_s }.sort.join(' / ')}</td>"
198
+ label += "</tr>"
199
+ end
200
+ label += "</table>>"
201
+ io.puts "\"#{s}\" [label = #{label}, pencolor = \"#000000\"];"
202
+
203
+ io.puts "\"#{la}\" -> \"#{s}\";"
204
+ io.puts "\"#{s}\" -> \"#{lb}\";"
205
+ end
206
+
207
+ io.puts "}"
208
+ io.string
209
+ end
210
+ f.puts dot
211
+ end
212
+ end
213
+ end
214
+
215
+ end
216
+
217
+ exit App.run(ARGV)
@@ -1,3 +1,3 @@
1
1
  module Neo4jBolt
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.9"
3
3
  end
data/lib/neo4j_bolt.rb CHANGED
@@ -5,12 +5,12 @@ require 'yaml'
5
5
 
6
6
  module Neo4jBolt
7
7
  class << self
8
- attr_accessor :bolt_host, :bolt_port
8
+ attr_accessor :bolt_host, :bolt_port, :bolt_verbosity
9
9
  end
10
10
  self.bolt_host = 'localhost'
11
11
  self.bolt_port = 7687
12
+ self.bolt_verbosity = 0
12
13
 
13
- NEO4J_DEBUG = 0
14
14
  CONSTRAINT_INDEX_PREFIX = 'neo4j_bolt_'
15
15
 
16
16
  module ServerState
@@ -115,7 +115,7 @@ module Neo4jBolt
115
115
  end
116
116
  chunk = @socket.read(length).unpack('C*')
117
117
  @data += chunk
118
- if NEO4J_DEBUG >= 3
118
+ if Neo4jBolt.bolt_verbosity >= 3
119
119
  dump()
120
120
  end
121
121
  end
@@ -753,7 +753,7 @@ module Neo4jBolt
753
753
  end
754
754
 
755
755
  def run_query(query, data = {}, &block)
756
- if NEO4J_DEBUG >= 1
756
+ if Neo4jBolt.bolt_verbosity >= 1
757
757
  STDERR.puts query
758
758
  STDERR.puts data.to_json
759
759
  STDERR.puts '-' * 40
@@ -791,7 +791,7 @@ module Neo4jBolt
791
791
  keys.each.with_index do |key, i|
792
792
  entry[key] = fix_value(data[:data][i])
793
793
  end
794
- if NEO4J_DEBUG >= 1
794
+ if Neo4jBolt.bolt_verbosity >= 1
795
795
  STDERR.puts ">>> #{entry.to_json}"
796
796
  STDERR.puts '-' * 40
797
797
  end
@@ -938,7 +938,7 @@ module Neo4jBolt
938
938
  transaction do
939
939
  node_count = neo4j_query_expect_one('MATCH (n) RETURN COUNT(n) as count;')['count']
940
940
  unless node_count == 0
941
- raise "Error: There are nodes in this database, exiting now."
941
+ raise "There are nodes in this database, exiting now."
942
942
  end
943
943
  end
944
944
  end
data/neo4j_bolt.gemspec CHANGED
@@ -22,8 +22,8 @@ Gem::Specification.new do |spec|
22
22
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
23
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
24
  end
25
- spec.bindir = "exe"
26
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.bindir = "bin"
26
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ["lib"]
28
28
 
29
29
  spec.add_development_dependency "rspec", "~> 3.2"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neo4j_bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Specht
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-28 00:00:00.000000000 Z
11
+ date: 2022-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -27,7 +27,10 @@ dependencies:
27
27
  description:
28
28
  email:
29
29
  - micha.specht@gmail.com
30
- executables: []
30
+ executables:
31
+ - console
32
+ - neo4j_bolt
33
+ - setup
31
34
  extensions: []
32
35
  extra_rdoc_files: []
33
36
  files:
@@ -40,6 +43,7 @@ files:
40
43
  - README.md
41
44
  - Rakefile
42
45
  - bin/console
46
+ - bin/neo4j_bolt
43
47
  - bin/setup
44
48
  - lib/neo4j_bolt.rb
45
49
  - lib/neo4j_bolt/version.rb