neo4j_bolt 0.1.2 → 0.1.3
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +39 -16
- data/lib/neo4j_bolt/version.rb +1 -1
- data/lib/neo4j_bolt.rb +29 -15
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4cc002cc5c04a6aa43ef9db40432dc77bb2a1cfa497e51509a44a9e978bc2ccb
|
4
|
+
data.tar.gz: d3ae31acea372c8b89daf38debd38b71ded70a6df589f970934bf0798fa2fb63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c50f906643998a24fd2eeb32ecd54c8ca9ba64715e6c16d10077d4fe281cae9a6e3184a20bee006afc4f1d94c06f387e6d6b611c82f29ef208638a332837129e
|
7
|
+
data.tar.gz: 65063c69802e4b54369ea5c78ddf4db4e1805140d6bfbd143a55317e369b952e0930fe091401866bb53d382b4157e363c461e44be2b3c39525cfa2bbe97a7068
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,16 +1,6 @@
|
|
1
1
|
# Neo4jBolt
|
2
2
|
|
3
|
-
A Neo4j/Bolt driver written in pure Ruby.
|
4
|
-
|
5
|
-
🚀 **Streaming support!** Neo4j sends responses in chunks of max. 64 kb. When running queries, specify a block to obtain rows as soon as they arrive.
|
6
|
-
|
7
|
-
## Supported and unsupported aspects
|
8
|
-
|
9
|
-
| | Supported | Unsupported |
|
10
|
-
|-|-|-
|
11
|
-
| Neo4j | 4.4 | 1.x 2.x 3.x <br /> 4.0 4.1 4.2 4.3 <br /> 5.x |
|
12
|
-
| Bolt | 4.4 | 1 2 3 4.0 4.1 4.2 4.3 |
|
13
|
-
|
3
|
+
A Neo4j/Bolt driver written in pure Ruby. Currently only supporting Neo4j 4.4.
|
14
4
|
|
15
5
|
## Installation
|
16
6
|
|
@@ -36,23 +26,56 @@ In order to use this gem, you need a running Neo4j database. You can start one u
|
|
36
26
|
docker run --rm --env NEO4J_AUTH=none --publish 7687:7687 neo4j:4.4-community
|
37
27
|
```
|
38
28
|
|
29
|
+
### Connecting to a Neo4j database
|
30
|
+
|
31
|
+
Specify your Bolt host and port (if you omit this it will be localhost:7687 by default):
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Neo4jBolt.bolt_host = 'localhost'
|
35
|
+
Neo4jBolt.bolt_port = 7687
|
36
|
+
```
|
37
|
+
|
38
|
+
Use `cleanup_neo4j` to disconnect (this is important when running a web app – it might be a good idea to close a socket once we're done with it so we don't run out of ports).
|
39
|
+
|
40
|
+
|
39
41
|
### Running queries
|
40
42
|
|
41
43
|
Use `neo4j_query` to run a query and receive all results:
|
42
44
|
|
43
45
|
```ruby
|
44
|
-
entries = neo4j_query("MATCH (n) RETURN n")
|
46
|
+
entries = neo4j_query("MATCH (n) RETURN n;")
|
45
47
|
```
|
46
48
|
Alternatively, specify a block to make use of Neo4j's streaming capabilities and receive entries one by one:
|
47
49
|
|
48
50
|
```ruby
|
49
|
-
neo4j_query("MATCH (n) RETURN n") do |entry|
|
50
|
-
# entry
|
51
|
+
neo4j_query("MATCH (n) RETURN n;") do |entry|
|
52
|
+
# handle entry here
|
51
53
|
end
|
52
54
|
```
|
53
|
-
Using streaming avoids memory hog since it prevents having to read all entries into memory before handling them.
|
54
55
|
|
55
|
-
|
56
|
+
Using streaming avoids memory hog since it prevents having to read all entries into memory before handling them. Nodes are returned as `Neo4jBolt::Node`, relationships as `Neo4jBolt::Relationship`. Both are subclasses of `Hash`, providing access to all properties plus a few extra details:
|
57
|
+
|
58
|
+
- `Neo4jBolt::Node`: `id`, `labels`
|
59
|
+
- `Neo4jBolt::Relationship`: `id`, `start_node_id`, `end_node_id`, `type`
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
node = neo4j_query_expect_one("CREATE (n:Node {a: 1, b: 2}) RETURN n;")['n']
|
63
|
+
# All nodes returned from Neo4j are a Neo4jBolt::Node
|
64
|
+
# It's a subclass of Hash and it stores all the node's
|
65
|
+
# properties plus two attributes called id and labels:
|
66
|
+
puts node.id
|
67
|
+
puts node.labels
|
68
|
+
puts node.keys
|
69
|
+
node.each_pair { |k, v| puts "#{k}: #{v}" }
|
70
|
+
puts node.to_json
|
71
|
+
```
|
72
|
+
Use `neo4j_query_expect_one` if you want to make sure there's exactly one entry to be returned:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
node = neo4j_query_expect_one("MATCH (n) RETURN n LIMIT 1;")['n']
|
76
|
+
```
|
77
|
+
|
78
|
+
If there's zero, two, or more results, this will raise a `ExpectedOneResultError`.
|
56
79
|
|
57
80
|
## Development
|
58
81
|
|
data/lib/neo4j_bolt/version.rb
CHANGED
data/lib/neo4j_bolt.rb
CHANGED
@@ -4,6 +4,12 @@ require 'json'
|
|
4
4
|
require 'yaml'
|
5
5
|
|
6
6
|
module Neo4jBolt
|
7
|
+
class << self
|
8
|
+
attr_accessor :bolt_host, :bolt_port
|
9
|
+
end
|
10
|
+
self.bolt_host = 'localhost'
|
11
|
+
self.bolt_port = 7687
|
12
|
+
|
7
13
|
NEO4J_DEBUG = 0
|
8
14
|
|
9
15
|
module ServerState
|
@@ -266,9 +272,7 @@ module Neo4jBolt
|
|
266
272
|
|
267
273
|
class BoltSocket
|
268
274
|
|
269
|
-
def initialize(
|
270
|
-
@host = host
|
271
|
-
@port = port
|
275
|
+
def initialize()
|
272
276
|
@socket = nil
|
273
277
|
@transaction = 0
|
274
278
|
@transaction_failed = false
|
@@ -594,8 +598,13 @@ module Neo4jBolt
|
|
594
598
|
append_uint8(0xb1)
|
595
599
|
append_token(BoltMarker::BOLT_RESET)
|
596
600
|
flush()
|
597
|
-
|
598
|
-
|
601
|
+
read_response() do |data|
|
602
|
+
if data[:marker] == BoltMarker::BOLT_SUCCESS
|
603
|
+
@state.set(ServerState::READY)
|
604
|
+
else
|
605
|
+
raise UnexpectedServerResponse.new(data[:marker])
|
606
|
+
end
|
607
|
+
end
|
599
608
|
# BoltBuffer.new(@socket).flush()
|
600
609
|
raise bolt_error(response_dict[:data]['code'], response_dict[:data]['message'])
|
601
610
|
end
|
@@ -607,7 +616,7 @@ module Neo4jBolt
|
|
607
616
|
|
608
617
|
def connect()
|
609
618
|
# STDERR.write "Connecting to Neo4j via Bolt..."
|
610
|
-
@socket = TCPSocket.new(
|
619
|
+
@socket = TCPSocket.new(Neo4jBolt.bolt_host, Neo4jBolt.bolt_port)
|
611
620
|
# @socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
|
612
621
|
# @socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 50)
|
613
622
|
# @socket.setsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10)
|
@@ -628,7 +637,7 @@ module Neo4jBolt
|
|
628
637
|
data = {
|
629
638
|
:routing => nil,
|
630
639
|
:scheme => 'none',
|
631
|
-
:user_agent => '
|
640
|
+
:user_agent => 'neo4j_bolt/0.1'
|
632
641
|
}
|
633
642
|
append_uint8(0xb1)
|
634
643
|
append_token(BoltMarker::BOLT_HELLO)
|
@@ -673,6 +682,8 @@ module Neo4jBolt
|
|
673
682
|
@transaction_failed = false
|
674
683
|
elsif data[:marker] == BoltMarker::BOLT_FAILURE
|
675
684
|
@state.set(ServerState::FAILED)
|
685
|
+
else
|
686
|
+
raise UnexpectedServerResponse.new(data[:marker])
|
676
687
|
end
|
677
688
|
end
|
678
689
|
end
|
@@ -709,10 +720,15 @@ module Neo4jBolt
|
|
709
720
|
append_uint8(0xb1)
|
710
721
|
append_token(BoltMarker::BOLT_COMMIT)
|
711
722
|
flush()
|
712
|
-
read_response()
|
713
|
-
|
714
|
-
|
715
|
-
|
723
|
+
read_response() do |data|
|
724
|
+
if data[:marker] == BoltMarker::BOLT_SUCCESS
|
725
|
+
@transaction = 0
|
726
|
+
@transaction_failed = false
|
727
|
+
@state.set(ServerState::READY)
|
728
|
+
else
|
729
|
+
raise UnexpectedServerResponse.new(data[:marker])
|
730
|
+
end
|
731
|
+
end
|
716
732
|
end
|
717
733
|
end
|
718
734
|
|
@@ -779,6 +795,8 @@ module Neo4jBolt
|
|
779
795
|
elsif data[:marker] == BoltMarker::BOLT_SUCCESS
|
780
796
|
# STDERR.puts data.to_yaml
|
781
797
|
@state.set(ServerState::TX_READY)
|
798
|
+
else
|
799
|
+
raise UnexpectedServerResponse.new(data[:marker])
|
782
800
|
end
|
783
801
|
end
|
784
802
|
elsif data[:marker] == BoltMarker::BOLT_FAILURE
|
@@ -811,10 +829,6 @@ module Neo4jBolt
|
|
811
829
|
end
|
812
830
|
end
|
813
831
|
|
814
|
-
def connect_bolt_socket(host, port)
|
815
|
-
@bolt_socket ||= BoltSocket.new(host, port)
|
816
|
-
end
|
817
|
-
|
818
832
|
def transaction(&block)
|
819
833
|
@bolt_socket ||= BoltSocket.new()
|
820
834
|
@bolt_socket.transaction { yield }
|
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.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Specht
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|