redgraph 0.1.1 → 0.2.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 +4 -4
- data/.github/workflows/main.yml +8 -0
- data/CHANGELOG.md +26 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +22 -1
- data/README.md +109 -15
- data/lib/redgraph.rb +16 -0
- data/lib/redgraph/edge.rb +17 -4
- data/lib/redgraph/graph.rb +44 -86
- data/lib/redgraph/graph/edge_methods.rb +105 -0
- data/lib/redgraph/graph/node_methods.rb +123 -0
- data/lib/redgraph/node.rb +11 -3
- data/lib/redgraph/node_model.rb +99 -0
- data/lib/redgraph/node_model/class_methods.rb +83 -0
- data/lib/redgraph/node_model/graph_manipulation.rb +24 -0
- data/lib/redgraph/node_model/persistence.rb +56 -0
- data/lib/redgraph/query_response.rb +91 -5
- data/lib/redgraph/util.rb +21 -0
- data/lib/redgraph/version.rb +1 -1
- data/redgraph.gemspec +2 -1
- data/test/graph_edge_methods_test.rb +100 -0
- data/test/graph_manipulation_test.rb +59 -0
- data/test/graph_node_methods_test.rb +112 -0
- data/test/graph_queries_test.rb +21 -66
- data/test/graph_test.rb +26 -0
- data/test/node_model_class_methods_test.rb +93 -0
- data/test/node_model_labels_test.rb +57 -0
- data/test/node_model_persistence_test.rb +70 -0
- data/test/node_model_test.rb +136 -0
- data/test/test_helper.rb +21 -0
- metadata +30 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fd53776ff217146cd6ca4924da40a43f5bf929fad03b73b79f32d371ea955e8
|
4
|
+
data.tar.gz: 551afc973f8e732ad532e74395e6c73251f14d68db73f667a207b234bd64163b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd7f88ae09acb7f09b6c8de949d4f31bbc52b12e4b914f035de99c7cd9b409c14eac3e592f834cc968517b796fed0cf3a085f7eba4915e630b2e66c424ae9870
|
7
|
+
data.tar.gz: 979aac39193d3150441ddf5baca14772a35c6cfd00f09df42752277aed3d955869822b2d97150209f1e71ad5ab95e566dc645d15d3e8262675dd858bd6fbb1dd
|
data/.github/workflows/main.yml
CHANGED
@@ -5,6 +5,12 @@ on: [push,pull_request]
|
|
5
5
|
jobs:
|
6
6
|
build:
|
7
7
|
runs-on: ubuntu-latest
|
8
|
+
|
9
|
+
services:
|
10
|
+
redis:
|
11
|
+
image: redislabs/redisgraph
|
12
|
+
ports: ["6379:6379"]
|
13
|
+
|
8
14
|
steps:
|
9
15
|
- uses: actions/checkout@v2
|
10
16
|
- name: Set up Ruby
|
@@ -12,6 +18,8 @@ jobs:
|
|
12
18
|
with:
|
13
19
|
ruby-version: 3.0.0
|
14
20
|
- name: Run the default task
|
21
|
+
env:
|
22
|
+
TEST_REDIS_URL: redis://localhost:6379/0
|
15
23
|
run: |
|
16
24
|
gem install bundler -v 2.2.15
|
17
25
|
bundle install
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
## [0.2.1]
|
2
|
+
|
3
|
+
- Add NodeModel#destroy method
|
4
|
+
- Add NodeModel.create method
|
5
|
+
|
6
|
+
## [0.2.0]
|
7
|
+
|
8
|
+
- revamp the NodeModel mixin, the Node to model mapping is now handled by the `_type` property
|
9
|
+
|
10
|
+
## [0.1.4]
|
11
|
+
|
12
|
+
- add NodeModel mixin for a basic ActiveRecord-like syntax
|
13
|
+
- add Graph#merge_node and Graph#merge_edge
|
14
|
+
- edge and node properties are now a HashWithIndifferentAccess
|
15
|
+
|
16
|
+
## [0.1.3] - 2021-04-13
|
17
|
+
|
18
|
+
- allow custom queries
|
19
|
+
- nodes and edges query now allow the `order` option
|
20
|
+
|
21
|
+
## [0.1.2] - 2021-04-12
|
22
|
+
|
23
|
+
- Add Graph#relationship_types
|
24
|
+
- Add Graph#count_nodes
|
25
|
+
- Add Graph#edges
|
26
|
+
|
1
27
|
## [0.1.1] - 2021-04-11
|
2
28
|
|
3
29
|
- Graph#nodes:
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,24 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
redgraph (0.
|
4
|
+
redgraph (0.2.1)
|
5
|
+
activesupport (>= 3.0.0)
|
5
6
|
redis (~> 4)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
11
|
+
activesupport (6.1.3.1)
|
12
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
|
+
i18n (>= 1.6, < 2)
|
14
|
+
minitest (>= 5.1)
|
15
|
+
tzinfo (~> 2.0)
|
16
|
+
zeitwerk (~> 2.3)
|
10
17
|
coderay (1.1.3)
|
18
|
+
concurrent-ruby (1.1.8)
|
19
|
+
docile (1.3.5)
|
20
|
+
i18n (1.8.10)
|
21
|
+
concurrent-ruby (~> 1.0)
|
11
22
|
method_source (1.0.0)
|
12
23
|
minitest (5.14.4)
|
13
24
|
pry (0.14.0)
|
@@ -15,6 +26,15 @@ GEM
|
|
15
26
|
method_source (~> 1.0)
|
16
27
|
rake (13.0.3)
|
17
28
|
redis (4.2.5)
|
29
|
+
simplecov (0.21.2)
|
30
|
+
docile (~> 1.1)
|
31
|
+
simplecov-html (~> 0.11)
|
32
|
+
simplecov_json_formatter (~> 0.1)
|
33
|
+
simplecov-html (0.12.3)
|
34
|
+
simplecov_json_formatter (0.1.2)
|
35
|
+
tzinfo (2.0.4)
|
36
|
+
concurrent-ruby (~> 1.0)
|
37
|
+
zeitwerk (2.4.2)
|
18
38
|
|
19
39
|
PLATFORMS
|
20
40
|
x86_64-darwin-20
|
@@ -24,6 +44,7 @@ DEPENDENCIES
|
|
24
44
|
pry (~> 0.14.0)
|
25
45
|
rake (~> 13.0)
|
26
46
|
redgraph!
|
47
|
+
simplecov (~> 0.21.2)
|
27
48
|
|
28
49
|
BUNDLED WITH
|
29
50
|
2.2.15
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Redgraph
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/redgraph)
|
4
|
+
[](https://codeclimate.com/github/pzac/redgraph)
|
5
|
+
|
3
6
|
A simple RedisGraph library. This gem owes **a lot** to the existing [redisgraph-rb](https://github.com/RedisGraph/redisgraph-rb) gem, but tries to provide a friendlier interface, similar to the existing [Python](https://github.com/RedisGraph/redisgraph-py) and [Elixir](https://github.com/crflynn/redisgraph-ex) clients.
|
4
7
|
|
5
8
|
## Installation
|
@@ -20,34 +23,127 @@ Or install it yourself as:
|
|
20
23
|
|
21
24
|
## Usage
|
22
25
|
|
26
|
+
The gem assumes you have a recent version of [RedisGraph](https://oss.redislabs.com/redisgraph/) up and running.
|
27
|
+
|
23
28
|
Basic usage:
|
24
29
|
|
25
|
-
|
30
|
+
```ruby
|
31
|
+
graph = Redgraph::Graph.new('movies', url: "redis://localhost:6379/1")
|
32
|
+
=> #<Redgraph::Graph:0x00007f8d5c2b7e38 @connection=#<Redis client v4.2.5 for redis://localhost:6379/1>, @graph_name="movies", @module_version=999999>
|
33
|
+
```
|
26
34
|
|
27
35
|
Create a couple nodes:
|
28
36
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
37
|
+
```ruby
|
38
|
+
actor = Redgraph::Node.new(label: 'actor', properties: {name: "Al Pacino"})
|
39
|
+
=> #<Redgraph::Node:0x00007f8d5f95cf88 @label="actor", @properties={:name=>"Al Pacino"}>
|
40
|
+
graph.add_node(actor)
|
41
|
+
=> #<Redgraph::Node:0x00007f8d5f95cf88 @id=0, @label="actor", @properties={:name=>"Al Pacino"}>
|
42
|
+
film = Redgraph::Node.new(label: 'film', properties: {name: "Scarface"})
|
43
|
+
=> #<Redgraph::Node:0x00007f8d5f85ccc8 @label="film", @properties={:name=>"Scarface"}>
|
44
|
+
graph.add_node(film)
|
45
|
+
=> #<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>
|
46
|
+
```
|
33
47
|
|
34
48
|
Create an edge between those nodes:
|
35
49
|
|
36
|
-
|
37
|
-
|
50
|
+
```ruby
|
51
|
+
edge = Redgraph::Edge.new(src: actor, dest: film, type: 'ACTOR_IN', properties: {role: "Tony Montana"})
|
52
|
+
=> #<Redgraph::Edge:0x00007f8d5f9ae3d8 @dest=#<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>, @dest_id=1, @properties={:role=>"Tony Montana"}, @src=#<Redgraph::Node:0x00007f8d5f95cf88 @id=0, @label="actor", @properties={:name=>"Al Pacino"}>, @src_id=0, @type="ACTOR_IN">
|
53
|
+
@graph.add_edge(edge)
|
54
|
+
=> #<Redgraph::Edge:0x00007f8d5f9ae3d8 @dest=#<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>, @dest_id=1, @id=0, @properties={:role=>"Tony Montana"}, @src=#<Redgraph::Node:0x00007f8d5f95cf88 @id=0, @label="actor", @properties={:name=>"Al Pacino"}>, @src_id=0, @type="ACTOR_IN">
|
55
|
+
```
|
56
|
+
|
57
|
+
You can merge nodes - the node will be created only if there isn't another with the same label and properties:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
graph.merge_node(film)
|
61
|
+
=> #<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>
|
62
|
+
```
|
63
|
+
|
64
|
+
Same with edges:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
@graph.merge_edge(edge)
|
68
|
+
=> #<Redgraph::Edge:0x00007f8d5f9ae3d8 @dest=#<Redgraph::Node:0x00007f8d5f85ccc8 @id=1, @label="film", @properties={:name=>"Scarface"}>, @dest_id=1, @id=0, @properties={:role=>"Tony Montana"}, @src=#<Redgraph::Node:0x00007f8d5f95cf88 @id=0, @label="actor", @properties={:name=>"Al Pacino"}>, @src_id=0, @type="ACTOR_IN">
|
69
|
+
```
|
38
70
|
|
39
71
|
Find a node by id:
|
40
72
|
|
41
|
-
|
73
|
+
```ruby
|
74
|
+
@graph.find_node_by_id(1)
|
75
|
+
=> #<Redgraph::Node:0x00007f8d5c2c6e88 @id=1, @label="film", @properties={"name"=>"Scarface"}>
|
76
|
+
```
|
42
77
|
|
43
78
|
To get all nodes:
|
44
79
|
|
45
|
-
|
80
|
+
```ruby
|
81
|
+
@graph.nodes
|
82
|
+
=> [#<Redgraph::Node:0x00007f8d5c2ee0a0 @id=0, @label="actor", @properties={"name"=>"Al Pacino"}>, #<Redgraph::Node:0x00007f8d5c2edfd8 @id=1, @label="film", @properties={"name"=>"Scarface"}>]
|
83
|
+
```
|
84
|
+
|
85
|
+
Optional filters that can be combined:
|
46
86
|
|
47
|
-
|
87
|
+
```ruby
|
88
|
+
@graph.nodes(label: 'actor')
|
89
|
+
@graph.nodes(properties: {name: "Al Pacino"})
|
90
|
+
@graph.nodes(limit: 10, skip: 20)
|
91
|
+
```
|
48
92
|
|
49
|
-
|
50
|
-
|
93
|
+
Counting nodes
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
@graph.count_nodes(label: 'actor')
|
97
|
+
=> 1
|
98
|
+
```
|
99
|
+
|
100
|
+
Getting edges:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
@graph.edges
|
104
|
+
@graph.edges(src: actor, dest: film)
|
105
|
+
@graph.edges(kind: 'FRIEND_OF', limit: 10, skip: 20)
|
106
|
+
@graph.count_edges
|
107
|
+
```
|
108
|
+
|
109
|
+
Running custom queries
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
@graph.query("MATCH (src)-[edge:FRIEND_OF]->(dest) RETURN src, edge")
|
113
|
+
```
|
114
|
+
|
115
|
+
### NodeModel
|
116
|
+
|
117
|
+
You can use the `NodeModel` mixin for a limited ActiveRecord-like interface:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
class Actor
|
121
|
+
include Redgraph::NodeModel
|
122
|
+
self.graph = Redgraph::Graph.new("movies", url: $REDIS_URL)
|
123
|
+
attribute :name
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
And this will give you stuff such as
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
Actor.count
|
131
|
+
john = Actor.new(name: "John Travolta")
|
132
|
+
john.add_to_graph # Will add the node to the graph
|
133
|
+
john.add_relation(type: "ACTED_IN", node: film, properties: {role: "Tony Manero"})
|
134
|
+
john.reload
|
135
|
+
john.destroy
|
136
|
+
Actor.create(name: "Al Pacino")
|
137
|
+
```
|
138
|
+
|
139
|
+
`NodeModel` models will automatically set a `_type` property to keep track of the object class.
|
140
|
+
|
141
|
+
You will then be able to run custom queries such as:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
Actor.query("MATCH (node) RETURN node ORDER BY node.name")
|
145
|
+
```
|
146
|
+
And the result rows object will be instances of the classes defined by the `_type` attribute.
|
51
147
|
|
52
148
|
## Development
|
53
149
|
|
@@ -55,7 +151,7 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
55
151
|
|
56
152
|
TEST_REDIS_URL=YOUR-REDIS-URL rake test
|
57
153
|
|
58
|
-
to run the tests.
|
154
|
+
to run the tests. Test coverage will be enabled if you set the `COVERAGE` environment variable to any value.
|
59
155
|
|
60
156
|
You can use a `TEST_REDIS_URL` such as `redis://localhost:6379/1`. Make sure you're not overwriting important databases.
|
61
157
|
|
@@ -63,8 +159,6 @@ You can also run `bin/console` for an interactive prompt that will allow you to
|
|
63
159
|
|
64
160
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
65
161
|
|
66
|
-
Run `bin/console` for an interactive prompt.
|
67
|
-
|
68
162
|
## Contributing
|
69
163
|
|
70
164
|
Bug reports and pull requests are welcome on GitHub at https://github.com/pzac/redgraph.
|
data/lib/redgraph.rb
CHANGED
@@ -1,13 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "redis"
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
4
|
+
require "active_support/core_ext/object/blank"
|
5
|
+
require "active_support/core_ext/string/inflections"
|
6
|
+
require "active_support/concern"
|
3
7
|
|
4
8
|
require_relative "redgraph/version"
|
9
|
+
require_relative "redgraph/util"
|
5
10
|
require_relative "redgraph/graph"
|
6
11
|
require_relative "redgraph/node"
|
7
12
|
require_relative "redgraph/edge"
|
8
13
|
require_relative "redgraph/query_response"
|
14
|
+
require_relative "redgraph/node_model"
|
9
15
|
|
10
16
|
module Redgraph
|
11
17
|
class Error < StandardError; end
|
12
18
|
class ServerError < Error; end
|
19
|
+
class MissingAliasPrefixError < Error
|
20
|
+
def message
|
21
|
+
"The order clause requires the node/edge alias prefix, ie order('node.foo') instead order('foo')"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
class MissingGraphError < Error
|
25
|
+
def message
|
26
|
+
"A graph to use is not defined"
|
27
|
+
end
|
28
|
+
end
|
13
29
|
end
|
data/lib/redgraph/edge.rb
CHANGED
@@ -2,17 +2,30 @@
|
|
2
2
|
|
3
3
|
module Redgraph
|
4
4
|
class Edge
|
5
|
-
|
5
|
+
include Util
|
6
6
|
|
7
|
-
|
7
|
+
attr_accessor :id, :src, :dest, :src_id, :dest_id, :type, :properties
|
8
|
+
|
9
|
+
def initialize(src: nil, dest: nil, type: nil, properties: {})
|
8
10
|
@src = src
|
11
|
+
@src_id = @src.id if @src
|
9
12
|
@dest = dest
|
13
|
+
@dest_id = @dest.id if @dest
|
10
14
|
@type = type
|
11
|
-
@properties = properties
|
15
|
+
@properties = (properties || {}).with_indifferent_access
|
12
16
|
end
|
13
17
|
|
14
18
|
def persisted?
|
15
|
-
|
19
|
+
id.present?
|
20
|
+
end
|
21
|
+
|
22
|
+
def ==(other)
|
23
|
+
super || other.instance_of?(self.class) && !id.nil? && other.id == id
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_query_string(item_alias: 'edge', src_alias: 'src', dest_alias: 'dest')
|
27
|
+
_type = ":#{type}" if type
|
28
|
+
"(#{src_alias})-[#{item_alias}#{_type} #{properties_to_string(properties)}]->(#{dest_alias})"
|
16
29
|
end
|
17
30
|
end
|
18
31
|
end
|
data/lib/redgraph/graph.rb
CHANGED
@@ -1,11 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "graph/node_methods"
|
4
|
+
require_relative "graph/edge_methods"
|
5
|
+
|
3
6
|
module Redgraph
|
4
7
|
class Graph
|
8
|
+
include NodeMethods
|
9
|
+
include EdgeMethods
|
10
|
+
include Util
|
11
|
+
|
5
12
|
attr_accessor :connection, :graph_name
|
6
13
|
|
7
|
-
|
8
|
-
|
14
|
+
# @example Graph.new("foobar", url: "redis://localhost:6379/0", logger: Logger.new(STDOUT))
|
15
|
+
# @param graph_name [String] Name of the graph
|
16
|
+
# @param redis_options [Hash] Redis client options
|
17
|
+
#
|
18
|
+
def initialize(graph_name, redis_options = {})
|
19
|
+
@graph_name = graph_name
|
9
20
|
@connection = Redis.new(redis_options)
|
10
21
|
@module_version = module_version
|
11
22
|
raise ServerError unless @module_version
|
@@ -29,120 +40,67 @@ module Redgraph
|
|
29
40
|
raise e
|
30
41
|
end
|
31
42
|
|
32
|
-
#
|
43
|
+
# @return [Array] Existing graph names
|
33
44
|
#
|
34
45
|
def list
|
35
46
|
@connection.call("GRAPH.LIST")
|
36
47
|
end
|
37
48
|
|
38
|
-
#
|
49
|
+
# @return [Array] Existing labels
|
39
50
|
#
|
40
51
|
def labels
|
41
|
-
result =
|
52
|
+
result = _query("CALL db.labels()")
|
42
53
|
result.resultset.map(&:values).flatten
|
43
54
|
end
|
44
55
|
|
45
|
-
#
|
56
|
+
# @return [Array] Existing properties
|
46
57
|
#
|
47
58
|
def properties
|
48
|
-
result =
|
59
|
+
result = _query("CALL db.propertyKeys()")
|
49
60
|
result.resultset.map(&:values).flatten
|
50
61
|
end
|
51
62
|
|
52
|
-
#
|
63
|
+
# @return [Array] Existing relationship types
|
53
64
|
#
|
54
|
-
def
|
55
|
-
result =
|
56
|
-
|
57
|
-
id = result.resultset.first["ID(n)"]
|
58
|
-
node.id = id
|
59
|
-
node
|
65
|
+
def relationship_types
|
66
|
+
result = _query("CALL db.relationshipTypes()")
|
67
|
+
result.resultset.map(&:values).flatten
|
60
68
|
end
|
61
69
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
(node_id, labels, properties) = result.resultset.first["node"]
|
66
|
-
attrs = {}
|
67
|
-
|
68
|
-
properties.each do |(index, type, value)|
|
69
|
-
attrs[get_property(index)] = value
|
70
|
-
end
|
71
|
-
Node.new(label: get_label(labels.first), properties: attrs).tap do |node|
|
72
|
-
node.id = node_id
|
73
|
-
end
|
70
|
+
# You can run custom cypher queries
|
71
|
+
def query(cmd)
|
72
|
+
_query(cmd).rows
|
74
73
|
end
|
75
74
|
|
76
|
-
#
|
75
|
+
# @param id [Integer] label id
|
76
|
+
# @return [String, nil] label
|
77
77
|
#
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
def get_label(id)
|
79
|
+
@labels ||= labels
|
80
|
+
@labels[id] || (@labels = labels)[id]
|
81
|
+
end
|
82
|
+
|
83
|
+
# @param id [Integer] property id
|
84
|
+
# @return [String, nil] property
|
82
85
|
#
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
_limit = "LIMIT #{limit}" if limit
|
87
|
-
_skip = "SKIP #{skip}" if skip
|
88
|
-
|
89
|
-
cmd = "MATCH (node#{_label} #{_props}) RETURN node #{_skip} #{_limit}"
|
90
|
-
result = query(cmd)
|
91
|
-
|
92
|
-
result.resultset.map do |item|
|
93
|
-
(node_id, labels, props) = item["node"]
|
94
|
-
attrs = {}
|
95
|
-
|
96
|
-
props.each do |(index, type, value)|
|
97
|
-
attrs[get_property(index)] = value
|
98
|
-
end
|
99
|
-
Node.new(label: get_label(labels.first), properties: attrs).tap do |node|
|
100
|
-
node.id = node_id
|
101
|
-
end
|
102
|
-
end
|
86
|
+
def get_property(id)
|
87
|
+
@properties ||= properties
|
88
|
+
@properties[id] || (@properties = properties)[id]
|
103
89
|
end
|
104
90
|
|
105
|
-
#
|
91
|
+
# @param id [Integer] relationship type id
|
92
|
+
# @return [String, nil] relationship type
|
106
93
|
#
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
CREATE (src)-[e:`#{edge.type}` #{quote_hash(edge.properties)}]->(dest) RETURN ID(e)")
|
111
|
-
return false if result.stats[:relationships_created] != 1
|
112
|
-
id = result.resultset.first["ID(e)"]
|
113
|
-
edge.id = id
|
114
|
-
edge
|
94
|
+
def get_relationship_type(id)
|
95
|
+
@relationship_types ||= relationship_types
|
96
|
+
@relationship_types[id] || (@relationship_types = relationship_types)[id]
|
115
97
|
end
|
116
98
|
|
117
99
|
private
|
118
100
|
|
119
|
-
def
|
101
|
+
def _query(cmd)
|
120
102
|
data = @connection.call("GRAPH.QUERY", graph_name, cmd, "--compact")
|
121
|
-
QueryResponse.new(data)
|
122
|
-
end
|
123
|
-
|
124
|
-
def quote_hash(hash)
|
125
|
-
"{" +
|
126
|
-
hash.map {|k,v| "#{k}:#{escape_value(v)}" }.join(", ") +
|
127
|
-
"}"
|
128
|
-
end
|
129
|
-
|
130
|
-
def escape_value(x)
|
131
|
-
case x
|
132
|
-
when Integer then x
|
133
|
-
else
|
134
|
-
"'#{x}'"
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def get_label(id)
|
139
|
-
@labels ||= labels
|
140
|
-
@labels[id] || (@labels = labels)[id]
|
141
|
-
end
|
142
|
-
|
143
|
-
def get_property(id)
|
144
|
-
@properties ||= properties
|
145
|
-
@properties[id] || (@properties = properties)[id]
|
103
|
+
QueryResponse.new(data, self)
|
146
104
|
end
|
147
105
|
end
|
148
106
|
end
|