neo4j_bolt 0.1.7 → 0.1.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 86471d4b049b4054a378f5084ae13dda181bd818a205ee4a67e6aa4bc5d0607f
4
- data.tar.gz: b1e855e4689946026eaa7971acb730577a57973b02605c893916d15e2438b1f3
3
+ metadata.gz: 1ac7e327b2ece44cd23a4408c81c0a9a41d52faf277c24b56280a15f1b79aeec
4
+ data.tar.gz: a24414f311a40ff6cb79d18a18497200f79ed7e2a58e070b5e321a4dc31cc757
5
5
  SHA512:
6
- metadata.gz: e4e414cb24861f58ae67f2a5c92da46f720c861fd49131befa16a9c046ea557d1e31fb40130fe892aa91b38d0ec3de881d4da94de4fde4a5288ab0add379c33f
7
- data.tar.gz: be8ed37b6ea0a7e358c25257eea3be90f78c2fd1342a4666bc244a5a379e241780a6df01d4005c4b26a4986a2fd24cd0a65f7569f4de19bcbf4a65517a33aa8a
6
+ metadata.gz: f716cd2380decb532dbe6954030e4ead5ea0a1edde1868922b81d2105801d7ed6bb9e5b35e3eb22f79ca9413408582bca6da44a9fa767ad6fa554b929df84436
7
+ data.tar.gz: 35f82570c1bcf2b56a61a17d9bbf189f2055386efd1c6f83cd3c60313069d26380ce050394665ede60ef9ea4eb27626bf7438b43a4070e361a2b9ed626c51893
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,213 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "neo4j_bolt"
5
+ require "gli"
6
+
7
+ include Neo4jBolt
8
+
9
+ class App
10
+ extend GLI::App
11
+
12
+ program_desc 'run various Neo4j housekeeping tasks'
13
+ version Neo4jBolt::VERSION
14
+
15
+ flag [:v, :verbosity], :default_value => 0
16
+ flag [:h, :host], :default_value => 'localhost:7687'
17
+
18
+ pre do |global_options, command, options, args|
19
+ host = global_options[:host]
20
+ Neo4jBolt.bolt_host = host.split(':').first
21
+ Neo4jBolt.bolt_port = host.split(':').last.to_i
22
+ Neo4jBolt.bolt_verbosity = global_options[:verbosity].to_i
23
+ true
24
+ end
25
+
26
+ # --------------------------------------------
27
+
28
+ desc 'Console'
29
+ command :console do |c|
30
+ c.action do
31
+ require "irb"
32
+ IRB.start(__FILE__)
33
+ end
34
+ end
35
+
36
+ # --------------------------------------------
37
+
38
+ desc 'Dump database'
39
+ long_desc 'Dump all nodes and relationships.'
40
+ command :dump do |c|
41
+ c.flag [:o, :out_file], :default_value => '/dev/stdout'
42
+ c.action do |global_options, options|
43
+ File.open(options[:out_file], 'w') do |f|
44
+ dump_database(f)
45
+ end
46
+ end
47
+ end
48
+
49
+ # --------------------------------------------
50
+
51
+ desc 'Load database dump'
52
+ long_desc 'Load nodes and relationships from a database dump.'
53
+ command :load do |c|
54
+ # c.flag [:i, :in_file], :desc => 'input path', :required => true
55
+ c.switch [:f, :force], :default_value => false, :desc => 'force appending nodes even if the database is not empty'
56
+ c.action do |global_options, options, args|
57
+ help_now!('input path is required') if args.empty?
58
+ path = args.shift
59
+ File.open(path, 'r') do |f|
60
+ load_database_dump(f, force_append: options[:force])
61
+ end
62
+ end
63
+ end
64
+
65
+ # --------------------------------------------
66
+
67
+ desc 'Clear database'
68
+ long_desc 'Clear all nodes and relationships'
69
+ command :clear do |c|
70
+ c.switch [:srsly], :required => true, :negatable => false, :desc => 'Specify --srsly to really clear the database'
71
+ c.action do |global_options, options, args|
72
+ if options[:srsly]
73
+ neo4j_query("MATCH (n) DETACH DELETE n;")
74
+ else
75
+ STDERR.puts "Doing nothing unless you specify --srsly."
76
+ end
77
+ end
78
+ end
79
+
80
+ # --------------------------------------------
81
+
82
+ desc 'Visualize database'
83
+ long_desc 'Generate a GraphViz-formatted visual representation of the database'
84
+ command :visualize do |c|
85
+ c.flag [:o, :out_file], :default_value => '/dev/stdout'
86
+ c.switch [:p, :properties], :default_value => false, :desc => 'include properties'
87
+ c.action do |global_options, options|
88
+ File.open(options[:out_file], 'w') do |f|
89
+ all_labels = Set.new()
90
+
91
+ TR = {'String' => 'string',
92
+ 'Array' => 'list',
93
+ 'Hash' => 'hash',
94
+ 'TrueClass' => 'true',
95
+ 'FalseClass' => 'false',
96
+ 'NilClass' => 'null',
97
+ 'Integer' => 'int',
98
+ 'Float' => 'float'
99
+ }
100
+
101
+ neo4j_query("MATCH (n) RETURN DISTINCT labels(n) AS labels") do |entry|
102
+ labels = entry['labels']
103
+ if labels.size != 1
104
+ raise "multiple labels per node not supported yet: #{labels.join(' ')}"
105
+ end
106
+ all_labels << labels.first
107
+ end
108
+
109
+ all_relationships = Set.new()
110
+
111
+ neo4j_query("MATCH (a)-[r]->(b) RETURN DISTINCT labels(a) AS la, type(r) AS t, labels(b) AS lb;") do |entry|
112
+ la = entry['la'].first
113
+ t = entry['t']
114
+ lb = entry['lb'].first
115
+ all_relationships << "#{la}/#{t}/#{lb}"
116
+ end
117
+
118
+ properties_for_label = {}
119
+ counts_for_label = {}
120
+
121
+ all_labels.to_a.sort.each do |label|
122
+ properties_for_label[label] ||= {}
123
+ if options[:properties]
124
+ neo4j_query("MATCH (n:#{label}) RETURN n") do |entry|
125
+ counts_for_label[label] ||= 0
126
+ counts_for_label[label] += 1
127
+ node = entry['n']
128
+ node.each_pair do |key, value|
129
+ properties_for_label[label][key] ||= {:classes => Set.new()}
130
+ properties_for_label[label][key][:classes] << value.class
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ all_relationships.each do |s|
137
+ properties_for_label[s] ||= {}
138
+ parts = s.split('/')
139
+ la = parts[0]
140
+ type = parts[1]
141
+ lb = parts[2]
142
+ if options[:properties]
143
+ neo4j_query("MATCH (a:#{la})-[r:#{type}]->(b:#{lb}) RETURN r") do |entry|
144
+ counts_for_label[s] ||= 0
145
+ counts_for_label[s] += 1
146
+ rel = entry['r']
147
+ rel.each_pair do |key, value|
148
+ properties_for_label[s][key] ||= {:classes => Set.new()}
149
+ properties_for_label[s][key][:classes] << value.class
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ dot = StringIO.open do |io|
156
+ io.puts "digraph {"
157
+ io.puts "graph [fontname = Helvetica, fontsize = 10, nodesep = 0.2, ranksep = 0.3];"
158
+ io.puts "node [fontname = Helvetica, fontsize = 10, shape = none, margin = 0];"
159
+ io.puts "edge [fontname = Helvetica, fontsize = 10, arrowsize = 0.6, color = \"#000000\"];"
160
+ io.puts 'rankdir=LR;'
161
+ io.puts 'splines=true;'
162
+ properties_for_label.keys.sort.each do |lbl|
163
+ label = "<<table valign='top' align='left' border='0' cellborder='0' cellspacing='0' cellpadding='4'>"
164
+ label += "<tr><td border='1' bgcolor='#fce94f' valign='top' align='left' colspan='2'><b>#{lbl}</b>"
165
+ if options[:properties]
166
+ label += " <i>(#{counts_for_label[lbl]})</i>"
167
+ end
168
+ label += "</td></tr>"
169
+ properties_for_label[lbl].keys.sort.each do |key|
170
+ label += "<tr>"
171
+ label += "<td border='1' valign='top' align='left' colspan='1'>#{key}</td>"
172
+ 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>"
173
+ label += "</tr>"
174
+ end
175
+ label += "</table>>"
176
+ io.puts "\"#{lbl}\" [label = #{label}, pencolor = \"#000000\"];"
177
+ end
178
+ all_relationships.each do |s|
179
+ parts = s.split('/')
180
+ la = parts[0]
181
+ type = parts[1]
182
+ lb = parts[2]
183
+
184
+ label = "<<table valign='top' align='left' border='0' cellborder='0' cellspacing='0' cellpadding='4'>"
185
+ label += "<tr><td border='1' bgcolor='#d3d7cf' valign='top' align='left' colspan='2'><b>#{type}</b>"
186
+ if options[:properties]
187
+ label += " <i>(#{counts_for_label[s]})</i>"
188
+ end
189
+ label += "</td></tr>"
190
+ (properties_for_label[s] || {}).keys.sort.each do |key|
191
+ label += "<tr>"
192
+ label += "<td border='1' valign='top' align='left' colspan='1'>#{key}</td>"
193
+ 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>"
194
+ label += "</tr>"
195
+ end
196
+ label += "</table>>"
197
+ io.puts "\"#{s}\" [label = #{label}, pencolor = \"#000000\"];"
198
+
199
+ io.puts "\"#{la}\" -> \"#{s}\";"
200
+ io.puts "\"#{s}\" -> \"#{lb}\";"
201
+ end
202
+
203
+ io.puts "}"
204
+ io.string
205
+ end
206
+ f.puts dot
207
+ end
208
+ end
209
+ end
210
+
211
+ end
212
+
213
+ exit App.run(ARGV)
@@ -1,3 +1,3 @@
1
1
  module Neo4jBolt
2
- VERSION = "0.1.7"
2
+ VERSION = "0.1.8"
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.8
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