neography 0.0.5 → 0.0.6
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.
- data/Gemfile.lock +1 -1
- data/README.rdoc +32 -5
- data/lib/neography.rb +0 -1
- data/lib/neography/node_relationship.rb +6 -16
- data/lib/neography/node_traverser.rb +117 -8
- data/lib/neography/relationship.rb +5 -1
- data/lib/neography/relationship_traverser.rb +26 -5
- data/lib/neography/version.rb +1 -1
- data/spec/integration/node_relationship_spec.rb +374 -0
- data/spec/integration/relationship_spec.rb +8 -42
- metadata +129 -128
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -157,10 +157,32 @@ The Neo4j ID is available by using node.neo_id .
|
|
157
157
|
new_rel = Neography::Relationship.create(:family, n1, n2) # Create a relationship from my_node to node2
|
158
158
|
new_rel.start_node # Get the start/from node of a relationship
|
159
159
|
new_rel.end_node # Get the end/to node of a relationship
|
160
|
+
new_rel.other_node(n2) # Get the other node of a relationship
|
161
|
+
|
160
162
|
existing_rel = Neography::Relationship.load(12) # Get an existing relationship by id
|
161
163
|
existing_rel.del # Delete a relationship
|
162
164
|
|
163
165
|
Neography::Relationship.create(:friends, n1, n2)
|
166
|
+
n1.outgoing(:friends) << n2 # Create outgoing relationship
|
167
|
+
n1.incoming(:friends) << n2 # Create incoming relationship
|
168
|
+
n1.both(:friends) << n2 # Create both relationships
|
169
|
+
|
170
|
+
n1.outgoing # Get nodes related by outgoing relationships
|
171
|
+
n1.incoming # Get nodes related by incoming relationships
|
172
|
+
n1.both # Get nodes related by any relationships
|
173
|
+
|
174
|
+
n1.outgoing(:friends) # Get nodes related by outgoing friends relationship
|
175
|
+
n1.incoming(:friends) # Get nodes related by incoming friends relationship
|
176
|
+
n1.both(:friends) # Get nodes related by friends relationship
|
177
|
+
|
178
|
+
n1.outgoing(:friends).incoming(:enemies) # Get nodes related by one of multiple relationships
|
179
|
+
n1.outgoing(:friends).depth(2) # Get nodes related by friends and friends of friends
|
180
|
+
n1.outgoing(:friends).depth(:all) # Get nodes related by friends until the end of the graph
|
181
|
+
n1.outgoing(:friends).depth(2).include_start_node # Get n1 and nodes related by friends and friends of friends
|
182
|
+
|
183
|
+
n1.outgoing(:friends).prune("position.endNode().getProperty('name') == 'Tom';")
|
184
|
+
n1.outgoing(:friends).filter("position.length() == 2;")
|
185
|
+
|
164
186
|
n1.rel?(:friends) # Has a friends relationship
|
165
187
|
n1.rel?(:outgoing, :friends) # Has outgoing friends relationship
|
166
188
|
n1.rel?(:friends, :outgoing) # same, just the other way
|
@@ -169,6 +191,12 @@ The Neo4j ID is available by using node.neo_id .
|
|
169
191
|
n1.rel?(:all) # same as above
|
170
192
|
n1.rel? # same as above
|
171
193
|
|
194
|
+
n1.rels # Get node relationships
|
195
|
+
n1.rels(:friends) # Get friends relationships
|
196
|
+
n1.rels(:friends).outgoing # Get outgoing friends relationships
|
197
|
+
n1.rels(:friends).incoming # Get incoming friends relationships
|
198
|
+
n1.rels(:friends,:work) # Get friends and work relationships
|
199
|
+
n1.rels(:friends,:work).outgoing # Get outgoing friends and work relationships
|
172
200
|
|
173
201
|
See Neo4j API for:
|
174
202
|
* {Order}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/graphdb/Traverser.Order.html]
|
@@ -185,12 +213,11 @@ A couple of examples borrowed from Matthew Deiters's Neo4jr-social
|
|
185
213
|
|
186
214
|
=== To Do
|
187
215
|
|
188
|
-
* More
|
189
|
-
* More
|
190
|
-
*
|
191
|
-
* create proper objects for Node and Relationship
|
216
|
+
* More Tests
|
217
|
+
* More Examples
|
218
|
+
* Mixins ?
|
192
219
|
|
193
|
-
===
|
220
|
+
=== Licenses
|
194
221
|
|
195
222
|
* Neography - MIT, see the LICENSE file http://github.com/maxdemarzi/neography/tree/master/LICENSE.
|
196
223
|
* Lucene - Apache, see http://lucene.apache.org/java/docs/features.html
|
data/lib/neography.rb
CHANGED
@@ -2,27 +2,15 @@ module Neography
|
|
2
2
|
module NodeRelationship
|
3
3
|
|
4
4
|
def outgoing(types=nil)
|
5
|
-
|
6
|
-
NodeTraverser.new(self).outgoing(types)
|
7
|
-
else
|
8
|
-
NodeTraverser.new(self).outgoing
|
9
|
-
end
|
5
|
+
NodeTraverser.new(self).outgoing(types)
|
10
6
|
end
|
11
7
|
|
12
8
|
def incoming(types=nil)
|
13
|
-
|
14
|
-
NodeTraverser.new(self).incoming(types)
|
15
|
-
else
|
16
|
-
NodeTraverser.new(self).incoming
|
17
|
-
end
|
9
|
+
NodeTraverser.new(self).incoming(types)
|
18
10
|
end
|
19
11
|
|
20
12
|
def both(types=nil)
|
21
|
-
|
22
|
-
NodeTraverser.new(self).both(types)
|
23
|
-
else
|
24
|
-
NodeTraverser.new(self) # default is both
|
25
|
-
end
|
13
|
+
NodeTraverser.new(self).both(types)
|
26
14
|
end
|
27
15
|
|
28
16
|
def rels(*types)
|
@@ -30,7 +18,9 @@ module Neography
|
|
30
18
|
end
|
31
19
|
|
32
20
|
def rel(dir, type)
|
33
|
-
Neography::RelationshipTraverser.new(self, type, dir)
|
21
|
+
rel = Neography::RelationshipTraverser.new(self, type, dir)
|
22
|
+
rel = rel.first unless rel.nil?
|
23
|
+
rel
|
34
24
|
end
|
35
25
|
|
36
26
|
def rel?(dir=nil, type=nil)
|
@@ -2,19 +2,128 @@ module Neography
|
|
2
2
|
class NodeTraverser
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
-
attr_accessor :order, :uniqueness, :depth, :prune, :filter
|
5
|
+
attr_accessor :order, :uniqueness, :depth, :prune, :filter, :relationships
|
6
6
|
|
7
|
-
def initialize(from, types = nil, dir=
|
7
|
+
def initialize(from, types = nil, dir = "all" )
|
8
8
|
@from = from
|
9
|
-
@depth = 1
|
10
9
|
@order = "depth first"
|
11
10
|
@uniqueness = "none"
|
12
|
-
|
13
|
-
|
11
|
+
@relationships = Array.new
|
12
|
+
types.each do |type|
|
13
|
+
@relationships << {"type" => type.to_s, "direction" => dir.to_s }
|
14
|
+
end unless types.nil?
|
15
|
+
end
|
16
|
+
|
17
|
+
def <<(other_node)
|
18
|
+
create(other_node)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def create(other_node)
|
23
|
+
case @relationships.first["direction"]
|
24
|
+
when "outgoing", "out"
|
25
|
+
rel = Neography::Relationship.new(@from.neo_server.create_relationship(@relationships.first["type"], @from, other_node))
|
26
|
+
when "incoming", "in"
|
27
|
+
rel = Neography::Relationship.new(@from.neo_server.create_relationship(@relationships.first["type"], other_node, @from))
|
28
|
+
else
|
29
|
+
rel = Array.new
|
30
|
+
rel << Neography::Relationship.new(@from.neo_server.create_relationship(@relationships.first["type"], @from, other_node))
|
31
|
+
rel << Neography::Relationship.new(@from.neo_server.create_relationship(@relationships.first["type"], other_node, @from))
|
32
|
+
end
|
33
|
+
rel
|
34
|
+
end
|
35
|
+
|
36
|
+
def both(type)
|
37
|
+
@relationships << {"type" => type.to_s, "direction" => "all"}
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def outgoing(type)
|
42
|
+
@relationships << {"type" => type.to_s, "direction" => "out"}
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def incoming(type)
|
47
|
+
@relationships << {"type" => type.to_s, "direction" => "in"}
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def filter(body)
|
52
|
+
@filter = Hash.new
|
53
|
+
@filter["language"] = "javascript"
|
54
|
+
@filter["body"] = body
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def prune(body)
|
59
|
+
@prune = Hash.new
|
60
|
+
@prune["language"] = "javascript"
|
61
|
+
@prune["body"] = body
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def depth(d)
|
66
|
+
d = 2147483647 if d == :all
|
67
|
+
@depth = d
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def include_start_node
|
72
|
+
@filter = Hash.new
|
73
|
+
@filter["language"] = "builtin"
|
74
|
+
@filter["name"] = "all"
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
def size
|
79
|
+
[*self].size
|
80
|
+
end
|
81
|
+
|
82
|
+
alias_method :length, :size
|
83
|
+
|
84
|
+
def [](index)
|
85
|
+
each_with_index {|node,i| break node if index == i}
|
86
|
+
end
|
87
|
+
|
88
|
+
def empty?
|
89
|
+
first == nil
|
90
|
+
end
|
91
|
+
|
92
|
+
def each
|
93
|
+
iterator.each do |i|
|
94
|
+
node = Neography::Node.new(i)
|
95
|
+
node.neo_server = @from.neo_server
|
96
|
+
yield node
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def iterator
|
101
|
+
options = Hash.new
|
102
|
+
options["order"] = @order
|
103
|
+
options["uniqueness"] = @uniqueness
|
104
|
+
options["relationships"] = @relationships
|
105
|
+
options["prune evaluator"] = @prune unless @prune.nil?
|
106
|
+
options["return filter"] = @filter unless @filter.nil?
|
107
|
+
options["depth"] = @depth unless @depth.nil?
|
108
|
+
|
109
|
+
if @relationships[0]["type"].blank?
|
110
|
+
rels = @from.neo_server.get_node_relationships(@from, @relationships[0]["direction"])
|
111
|
+
case @relationships[0]["direction"]
|
112
|
+
when "in"
|
113
|
+
rels.collect { |r| @from.neo_server.get_node(r["start"]) } #.uniq
|
114
|
+
when "out"
|
115
|
+
rels.collect { |r| @from.neo_server.get_node(r["end"]) } #.uniq
|
116
|
+
else
|
117
|
+
rels.collect { |r|
|
118
|
+
if @from.neo_id == r["start"].split('/').last
|
119
|
+
@from.neo_server.get_node(r["end"])
|
120
|
+
else
|
121
|
+
@from.neo_server.get_node(r["start"])
|
122
|
+
end
|
123
|
+
} #.uniq
|
124
|
+
end
|
14
125
|
else
|
15
|
-
|
16
|
-
# @dir = dir_to_java(dir)
|
17
|
-
# @td = org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl.new.breadth_first().relationships(@type, @dir)
|
126
|
+
@from.neo_server.traverse(@from, "nodes", options)
|
18
127
|
end
|
19
128
|
end
|
20
129
|
|
@@ -42,8 +42,12 @@ module Neography
|
|
42
42
|
self.start_node.neo_server.delete_relationship(self.neo_id)
|
43
43
|
end
|
44
44
|
|
45
|
+
def exist?
|
46
|
+
!self.start_node.neo_server.get_relationship(self.neo_id).nil?
|
47
|
+
end
|
48
|
+
|
45
49
|
def other_node(node)
|
46
|
-
if node
|
50
|
+
if node == @start_node
|
47
51
|
@end_node
|
48
52
|
else
|
49
53
|
@start_node
|
@@ -19,15 +19,38 @@ module Neography
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def each
|
22
|
-
iterator.each
|
22
|
+
iterator.each do |i|
|
23
|
+
rel = Neography::Relationship.new(i, @node.neo_server)
|
24
|
+
rel.start_node = Neography::Node.load(rel.start_node)
|
25
|
+
rel.end_node = Neography::Node.load(rel.end_node)
|
26
|
+
|
27
|
+
yield rel if match_to_other?(rel)
|
28
|
+
end
|
23
29
|
end
|
24
30
|
|
25
31
|
def empty?
|
26
32
|
first == nil
|
27
33
|
end
|
28
|
-
|
34
|
+
|
29
35
|
def iterator
|
30
|
-
@node.neo_server.get_node_relationships(@node, @direction, @types)
|
36
|
+
Array(@node.neo_server.get_node_relationships(@node, @direction, @types))
|
37
|
+
end
|
38
|
+
|
39
|
+
def match_to_other?(rel)
|
40
|
+
if @to_other.nil?
|
41
|
+
true
|
42
|
+
elsif @direction == :outgoing
|
43
|
+
rel.end_node == @to_other
|
44
|
+
elsif @direction == :incoming
|
45
|
+
rel.start_node == @to_other
|
46
|
+
else
|
47
|
+
rel.start_node == @to_other || rel.end_node == @to_other
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_other(to_other)
|
52
|
+
@to_other = to_other
|
53
|
+
self
|
31
54
|
end
|
32
55
|
|
33
56
|
def del
|
@@ -44,13 +67,11 @@ module Neography
|
|
44
67
|
end
|
45
68
|
|
46
69
|
def incoming
|
47
|
-
raise "Not allowed calling incoming when finding several relationships types" if @types
|
48
70
|
@direction = :incoming
|
49
71
|
self
|
50
72
|
end
|
51
73
|
|
52
74
|
def outgoing
|
53
|
-
raise "Not allowed calling outgoing when finding several relationships types" if @types
|
54
75
|
@direction = :outgoing
|
55
76
|
self
|
56
77
|
end
|
data/lib/neography/version.rb
CHANGED
@@ -0,0 +1,374 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Neography::NodeRelationship do
|
4
|
+
|
5
|
+
def create_nodes
|
6
|
+
#
|
7
|
+
# f
|
8
|
+
# ^
|
9
|
+
# friends
|
10
|
+
# |
|
11
|
+
# a --friends-> b --friends--> c
|
12
|
+
# | ^
|
13
|
+
# | |
|
14
|
+
# +--- work -----+
|
15
|
+
# |
|
16
|
+
# +--- work ---> d --- work --> e
|
17
|
+
a = Neography::Node.create :name => 'a'
|
18
|
+
b = Neography::Node.create :name => 'b'
|
19
|
+
c = Neography::Node.create :name => 'c'
|
20
|
+
d = Neography::Node.create :name => 'd'
|
21
|
+
e = Neography::Node.create :name => 'e'
|
22
|
+
f = Neography::Node.create :name => 'f'
|
23
|
+
a.outgoing(:friends) << b
|
24
|
+
b.outgoing(:friends) << c
|
25
|
+
b.outgoing(:work) << c
|
26
|
+
b.outgoing(:work) << d
|
27
|
+
d.outgoing(:work) << e
|
28
|
+
b.outgoing(:friends) << f
|
29
|
+
[a,b,c,d,e,f]
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "outgoing" do
|
33
|
+
it "#outgoing(:friends) << other_node creates an outgoing relationship of type :friends" do
|
34
|
+
a = Neography::Node.create
|
35
|
+
other_node = Neography::Node.create
|
36
|
+
|
37
|
+
# when
|
38
|
+
a.outgoing(:friends) << other_node
|
39
|
+
|
40
|
+
# then
|
41
|
+
a.outgoing(:friends).first.should == other_node
|
42
|
+
end
|
43
|
+
|
44
|
+
it "#outgoing(:friends) << b << c creates an outgoing relationship of type :friends" do
|
45
|
+
a = Neography::Node.create
|
46
|
+
b = Neography::Node.create
|
47
|
+
c = Neography::Node.create
|
48
|
+
|
49
|
+
# when
|
50
|
+
a.outgoing(:friends) << b << c
|
51
|
+
|
52
|
+
# then
|
53
|
+
a.outgoing(:friends).should include(b,c)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "#outgoing returns all incoming nodes of any type" do
|
57
|
+
a,b,c,d,e,f = create_nodes
|
58
|
+
|
59
|
+
b.outgoing.should include(c,f,d)
|
60
|
+
[*b.outgoing].size.should == 4 #c is related by both work and friends
|
61
|
+
end
|
62
|
+
|
63
|
+
it "#outgoing(type) should only return outgoing nodes of the given type of depth one" do
|
64
|
+
a,b,c,d = create_nodes
|
65
|
+
b.outgoing(:work).should include(c,d)
|
66
|
+
[*b.outgoing(:work)].size.should == 2
|
67
|
+
end
|
68
|
+
|
69
|
+
it "#outgoing(type1).outgoing(type2) should return outgoing nodes of the given types" do
|
70
|
+
a,b,c,d,e,f = create_nodes
|
71
|
+
nodes = b.outgoing(:work).outgoing(:friends)
|
72
|
+
|
73
|
+
nodes.should include(c,d,f)
|
74
|
+
nodes.size.should == 4 #c is related by both work and friends
|
75
|
+
end
|
76
|
+
|
77
|
+
it "#outgoing(type).depth(4) should only return outgoing nodes of the given type and depth" do
|
78
|
+
a,b,c,d,e = create_nodes
|
79
|
+
[*b.outgoing(:work).depth(4)].size.should == 3
|
80
|
+
b.outgoing(:work).depth(4).should include(c,d,e)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "#outgoing(type).depth(4).include_start_node should also include the start node" do
|
84
|
+
a,b,c,d,e = create_nodes
|
85
|
+
[*b.outgoing(:work).depth(4).include_start_node].size.should == 4
|
86
|
+
b.outgoing(:work).depth(4).include_start_node.should include(b,c,d,e)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "#outgoing(type).depth(:all) should traverse at any depth" do
|
90
|
+
a,b,c,d,e = create_nodes
|
91
|
+
[*b.outgoing(:work).depth(:all)].size.should == 3
|
92
|
+
b.outgoing(:work).depth(:all).should include(c,d,e)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "incoming" do
|
97
|
+
it "#incoming(:friends) << other_node should add an incoming relationship" do
|
98
|
+
a = Neography::Node.create
|
99
|
+
other_node = Neography::Node.create
|
100
|
+
|
101
|
+
# when
|
102
|
+
a.incoming(:friends) << other_node
|
103
|
+
|
104
|
+
# then
|
105
|
+
a.incoming(:friends).first.should == other_node
|
106
|
+
end
|
107
|
+
|
108
|
+
it "#incoming(:friends) << b << c creates an incoming relationship of type :friends" do
|
109
|
+
a = Neography::Node.create
|
110
|
+
b = Neography::Node.create
|
111
|
+
c = Neography::Node.create
|
112
|
+
|
113
|
+
# when
|
114
|
+
a.incoming(:friends) << b << c
|
115
|
+
|
116
|
+
# then
|
117
|
+
a.incoming(:friends).should include(b,c)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "#incoming returns all incoming nodes of any type" do
|
121
|
+
a,b,c,d,e,f = create_nodes
|
122
|
+
|
123
|
+
b.incoming.should include(a)
|
124
|
+
[*b.incoming].size.should == 1
|
125
|
+
end
|
126
|
+
|
127
|
+
it "#incoming(type).depth(2) should only return outgoing nodes of the given type and depth" do
|
128
|
+
a,b,c,d,e = create_nodes
|
129
|
+
[*e.incoming(:work).depth(2)].size.should == 2
|
130
|
+
e.incoming(:work).depth(2).should include(b,d)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "#incoming(type) should only return incoming nodes of the given type of depth one" do
|
134
|
+
a,b,c,d = create_nodes
|
135
|
+
c.incoming(:work).should include(b)
|
136
|
+
[*c.incoming(:work)].size.should == 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "both" do
|
141
|
+
it "#both(:friends) << other_node should raise an exception" do
|
142
|
+
a = Neography::Node.create
|
143
|
+
other_node = Neography::Node.create
|
144
|
+
|
145
|
+
# when
|
146
|
+
a.both(:friends) << other_node
|
147
|
+
a.incoming(:friends).first.should == other_node
|
148
|
+
a.outgoing(:friends).first.should == other_node
|
149
|
+
end
|
150
|
+
|
151
|
+
it "#both returns all incoming and outgoing nodes of any type" do
|
152
|
+
a,b,c,d,e,f = create_nodes
|
153
|
+
|
154
|
+
b.both.should include(a,c,d,f)
|
155
|
+
[*b.both].size.should == 5 #c is related by both work and friends
|
156
|
+
b.incoming.should include(a)
|
157
|
+
b.outgoing.should include(c)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "#both(type) should return both incoming and outgoing nodes of the given type of depth one" do
|
161
|
+
a,b,c,d,e,f = create_nodes
|
162
|
+
|
163
|
+
b.both(:friends).should include(a,c,f)
|
164
|
+
[*b.both(:friends)].size.should == 3
|
165
|
+
end
|
166
|
+
|
167
|
+
it "#outgoing and #incoming can be combined to traverse several relationship types" do
|
168
|
+
a,b,c,d,e = create_nodes
|
169
|
+
nodes = [*b.incoming(:friends).outgoing(:work)]
|
170
|
+
|
171
|
+
nodes.should include(a,c,d)
|
172
|
+
nodes.should_not include(b,e)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
describe "prune" do
|
178
|
+
it "#prune, if it returns true the traversal will be stop for that path" do
|
179
|
+
a, b, c, d, e = create_nodes
|
180
|
+
[*b.outgoing(:work).depth(4)].size.should == 3
|
181
|
+
b.outgoing(:work).depth(4).should include(c,d,e)
|
182
|
+
|
183
|
+
[*b.outgoing(:work).prune("position.endNode().getProperty('name') == 'd';")].size.should == 2
|
184
|
+
b.outgoing(:work).prune("position.endNode().getProperty('name') == 'd';").should include(c,d)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe "filter" do
|
189
|
+
it "#filter, if it returns true the node will be included in the return results" do
|
190
|
+
a, b, c, d, e = create_nodes
|
191
|
+
[*b.outgoing(:work).depth(4)].size.should == 3
|
192
|
+
b.outgoing(:work).depth(4).should include(c,d,e)
|
193
|
+
|
194
|
+
[*b.outgoing(:work).depth(4).filter("position.length() == 2;")].size.should == 1
|
195
|
+
b.outgoing(:work).depth(4).filter("position.length() == 2;").should include(e)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "rels" do
|
200
|
+
it "#rels returns a RelationshipTraverser which can filter which relationship it should return by specifying #to_other" do
|
201
|
+
a = Neography::Node.create
|
202
|
+
b = Neography::Node.create
|
203
|
+
c = Neography::Node.create
|
204
|
+
r1 = Neography::Relationship.create(:friend, a, b)
|
205
|
+
Neography::Relationship.create(:friend, a, c)
|
206
|
+
|
207
|
+
a.rels.to_other(b).size.should == 1
|
208
|
+
a.rels.to_other(b).should include(r1)
|
209
|
+
end
|
210
|
+
|
211
|
+
it "#rels returns an RelationshipTraverser which provides a method for deleting all the relationships" do
|
212
|
+
a = Neography::Node.create
|
213
|
+
b = Neography::Node.create
|
214
|
+
c = Neography::Node.create
|
215
|
+
r1 = Neography::Relationship.create(:friend, a, b)
|
216
|
+
r2 = Neography::Relationship.create(:friend, a, c)
|
217
|
+
|
218
|
+
a.rel?(:friend).should be_true
|
219
|
+
a.rels.del
|
220
|
+
a.rel?(:friend).should be_false
|
221
|
+
r1.exist?.should be_false
|
222
|
+
r2.exist?.should be_false
|
223
|
+
end
|
224
|
+
|
225
|
+
it "#rels returns an RelationshipTraverser with methods #del and #to_other which can be combined to only delete a subset of the relationships" do
|
226
|
+
a = Neography::Node.create
|
227
|
+
b = Neography::Node.create
|
228
|
+
c = Neography::Node.create
|
229
|
+
r1 = Neography::Relationship.create(:friend, a, b)
|
230
|
+
r2 = Neography::Relationship.create(:friend, a, c)
|
231
|
+
r1.exist?.should be_true
|
232
|
+
r2.exist?.should be_true
|
233
|
+
a.rels.to_other(c).del
|
234
|
+
r1.exist?.should be_true
|
235
|
+
r2.exist?.should be_false
|
236
|
+
end
|
237
|
+
|
238
|
+
it "#rels should return both incoming and outgoing relationship of any type of depth one" do
|
239
|
+
a,b,c,d,e,f = create_nodes
|
240
|
+
b.rels.size.should == 5
|
241
|
+
nodes = b.rels.collect{|r| r.other_node(b)}
|
242
|
+
nodes.should include(a,c,d,f)
|
243
|
+
nodes.should_not include(e)
|
244
|
+
end
|
245
|
+
|
246
|
+
it "#rels(:friends) should return both incoming and outgoing relationships of given type of depth one" do
|
247
|
+
# given
|
248
|
+
a,b,c,d,e,f = create_nodes
|
249
|
+
|
250
|
+
# when
|
251
|
+
rels = [*b.rels(:friends)]
|
252
|
+
|
253
|
+
# then
|
254
|
+
rels.size.should == 3
|
255
|
+
nodes = rels.collect{|r| r.end_node}
|
256
|
+
nodes.should include(b,c,f)
|
257
|
+
nodes.should_not include(a,d,e)
|
258
|
+
end
|
259
|
+
|
260
|
+
it "#rels(:friends).outgoing should return only outgoing relationships of given type of depth one" do
|
261
|
+
# given
|
262
|
+
a,b,c,d,e,f = create_nodes
|
263
|
+
|
264
|
+
# when
|
265
|
+
rels = [*b.rels(:friends).outgoing]
|
266
|
+
|
267
|
+
# then
|
268
|
+
rels.size.should == 2
|
269
|
+
nodes = rels.collect{|r| r.end_node}
|
270
|
+
nodes.should include(c,f)
|
271
|
+
nodes.should_not include(a,b,d,e)
|
272
|
+
end
|
273
|
+
|
274
|
+
|
275
|
+
it "#rels(:friends).incoming should return only outgoing relationships of given type of depth one" do
|
276
|
+
# given
|
277
|
+
a,b,c,d,e = create_nodes
|
278
|
+
|
279
|
+
# when
|
280
|
+
rels = [*b.rels(:friends).incoming]
|
281
|
+
|
282
|
+
# then
|
283
|
+
rels.size.should == 1
|
284
|
+
nodes = rels.collect{|r| r.start_node}
|
285
|
+
nodes.should include(a)
|
286
|
+
nodes.should_not include(b,c,d,e)
|
287
|
+
end
|
288
|
+
|
289
|
+
it "#rels(:friends,:work) should return both incoming and outgoing relationships of given types of depth one" do
|
290
|
+
# given
|
291
|
+
a,b,c,d,e,f = create_nodes
|
292
|
+
|
293
|
+
# when
|
294
|
+
rels = [*b.rels(:friends,:work)]
|
295
|
+
|
296
|
+
# then
|
297
|
+
rels.size.should == 5
|
298
|
+
nodes = rels.collect{|r| r.other_node(b)}
|
299
|
+
nodes.should include(a,c,d,f)
|
300
|
+
nodes.should_not include(b,e)
|
301
|
+
end
|
302
|
+
|
303
|
+
it "#rels(:friends,:work).outgoing should return outgoing relationships of given types of depth one" do
|
304
|
+
# given
|
305
|
+
a,b,c,d,e,f = create_nodes
|
306
|
+
|
307
|
+
# when
|
308
|
+
rels = [*b.rels(:friends,:work).outgoing]
|
309
|
+
|
310
|
+
# then
|
311
|
+
rels.size.should == 4
|
312
|
+
nodes = rels.collect{|r| r.other_node(b)}
|
313
|
+
nodes.should include(c,d,f)
|
314
|
+
nodes.should_not include(a,b,e)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
describe "rel" do
|
319
|
+
it "#rel returns a single relationship if there is only one relationship" do
|
320
|
+
a = Neography::Node.create
|
321
|
+
b = Neography::Node.create
|
322
|
+
rel = Neography::Relationship.create(:friend, a, b)
|
323
|
+
a.rel(:outgoing, :friend).should == rel
|
324
|
+
end
|
325
|
+
|
326
|
+
it "#rel returns nil if there is no relationship" do
|
327
|
+
a = Neography::Node.create
|
328
|
+
b = Neography::Node.create
|
329
|
+
a.rel(:outgoing, :friend).should be_nil
|
330
|
+
end
|
331
|
+
|
332
|
+
it "#rel should only return one relationship even if there are more" do
|
333
|
+
a = Neography::Node.create
|
334
|
+
b = Neography::Node.create
|
335
|
+
c = Neography::Node.create
|
336
|
+
Neography::Relationship.create(:friend, a, b)
|
337
|
+
Neography::Relationship.create(:friend, a, c)
|
338
|
+
[*a.rel(:outgoing, :friend)].size == 1
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
describe "rel?" do
|
343
|
+
it "#rel? returns true if there are any relationships" do
|
344
|
+
n1 = Neography::Node.create
|
345
|
+
n1.rel?.should be_false
|
346
|
+
n1.outgoing(:foo) << Neography::Node.create
|
347
|
+
|
348
|
+
n1.rel?.should be_true
|
349
|
+
n1.rel?(:bar).should be_false
|
350
|
+
n1.rel?(:foo).should be_true
|
351
|
+
n1.rel?(:incoming, :foo).should be_false
|
352
|
+
n1.rel?(:outgoing, :foo).should be_true
|
353
|
+
n1.rel?(:foo, :incoming).should be_false
|
354
|
+
n1.rel?(:foo, :outgoing).should be_true
|
355
|
+
n1.rel?(:incoming).should be_false
|
356
|
+
n1.rel?(:outgoing).should be_true
|
357
|
+
n1.rel?(:both).should be_true
|
358
|
+
n1.rel?(:all).should be_true
|
359
|
+
n1.rel?.should be_true
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
|
364
|
+
describe "delete relationship" do
|
365
|
+
it "can delete an existing relationship" do
|
366
|
+
p1 = Neography::Node.create
|
367
|
+
p2 = Neography::Node.create
|
368
|
+
new_rel = Neography::Relationship.create(:family, p1, p2)
|
369
|
+
new_rel.del
|
370
|
+
Neography::Relationship.load(new_rel).should be_nil
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
@@ -6,21 +6,16 @@ describe Neography::Relationship do
|
|
6
6
|
p1 = Neography::Node.create
|
7
7
|
p2 = Neography::Node.create
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
new_rel.end_node.should == p2
|
13
|
-
|
14
|
-
|
15
|
-
# p1.outgoing(:family).should include(p2)
|
16
|
-
# p2.incoming(:family).should include(p1)
|
9
|
+
Neography::Relationship.create(:family, p1, p2)
|
10
|
+
p1.outgoing(:family).should include(p2)
|
11
|
+
p2.incoming(:family).should include(p1)
|
17
12
|
end
|
18
13
|
|
19
14
|
it "#new(:family, p1, p2, :since => '1998', :colour => 'blue') creates relationship and sets its properties" do
|
20
15
|
p1 = Neography::Node.create
|
21
16
|
p2 = Neography::Node.create
|
22
|
-
|
23
17
|
rel = Neography::Relationship.create(:family, p1, p2, :since => 1998, :colour => 'blue')
|
18
|
+
|
24
19
|
rel[:since].should == 1998
|
25
20
|
rel[:colour].should == 'blue'
|
26
21
|
rel.since.should == 1998
|
@@ -30,42 +25,13 @@ describe Neography::Relationship do
|
|
30
25
|
it "#outgoing(:friends).create(other) creates a new relationship between self and other node" do
|
31
26
|
p1 = Neography::Node.create
|
32
27
|
p2 = Neography::Node.create
|
33
|
-
|
34
28
|
rel = p1.outgoing(:foo).create(p2)
|
35
|
-
p1.outgoing(:foo).first.should == p2
|
36
|
-
rel.should be_kind_of(Neography::Relationship)
|
37
|
-
end
|
38
|
-
end
|
39
29
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
new_rel = Neography::Relationship.create(:foo, n1, n2)
|
45
|
-
n1.rel?.should be_true
|
46
|
-
n1.rel?(:bar).should be_false
|
47
|
-
n1.rel?(:foo).should be_true
|
48
|
-
n1.rel?(:incoming, :foo).should be_false
|
49
|
-
n1.rel?(:outgoing, :foo).should be_true
|
50
|
-
n1.rel?(:foo, :incoming).should be_false
|
51
|
-
n1.rel?(:foo, :outgoing).should be_true
|
52
|
-
|
53
|
-
n1.rel?(:incoming).should be_false
|
54
|
-
n1.rel?(:outgoing).should be_true
|
55
|
-
n1.rel?(:both).should be_true
|
56
|
-
n1.rel?(:all).should be_true
|
57
|
-
n1.rel?.should be_true
|
30
|
+
rel.should be_kind_of(Neography::Relationship)
|
31
|
+
p1.outgoing(:foo).first.should == p2
|
32
|
+
p1.outgoing(:foo).should include(p2)
|
33
|
+
p2.incoming(:foo).should include(p1)
|
58
34
|
end
|
59
35
|
end
|
60
36
|
|
61
|
-
|
62
|
-
describe "delete relationship" do
|
63
|
-
it "can delete an existing relationship" do
|
64
|
-
p1 = Neography::Node.create
|
65
|
-
p2 = Neography::Node.create
|
66
|
-
new_rel = Neography::Relationship.create(:family, p1, p2)
|
67
|
-
new_rel.del
|
68
|
-
Neography::Relationship.load(new_rel).should be_nil
|
69
|
-
end
|
70
|
-
end
|
71
37
|
end
|
metadata
CHANGED
@@ -3,95 +3,95 @@ name: neography
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
version: 0.0.
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
version: 0.0.6
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
|
-
|
12
|
+
- Max De Marzi
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-12-
|
17
|
+
date: 2010-12-10 00:00:00 -08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 2
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
- beta
|
33
|
+
- 22
|
34
|
+
version: 2.0.0.beta.22
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: net-http-spy
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 2
|
48
|
+
- 1
|
49
|
+
version: 0.2.1
|
50
|
+
type: :development
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: fakeweb
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
segments:
|
61
|
+
- 1
|
62
|
+
- 3
|
63
|
+
- 0
|
64
|
+
version: 1.3.0
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: httparty
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
- 6
|
78
|
+
- 1
|
79
|
+
version: 0.6.1
|
80
|
+
type: :runtime
|
81
|
+
version_requirements: *id004
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: json
|
84
|
+
prerelease: false
|
85
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
type: :runtime
|
94
|
+
version_requirements: *id005
|
95
95
|
description: A Ruby wrapper to the Neo4j Rest API see http://components.neo4j.org/neo4j-rest/ for more details.
|
96
96
|
email: maxdemarzi@gmail.com
|
97
97
|
executables: []
|
@@ -101,42 +101,43 @@ extensions: []
|
|
101
101
|
extra_rdoc_files: []
|
102
102
|
|
103
103
|
files:
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
104
|
+
- .gitignore
|
105
|
+
- CONTRIBUTORS
|
106
|
+
- Gemfile
|
107
|
+
- Gemfile.lock
|
108
|
+
- LICENSE
|
109
|
+
- README.rdoc
|
110
|
+
- Rakefile
|
111
|
+
- examples/facebook.rb
|
112
|
+
- examples/linkedin.rb
|
113
|
+
- examples/traversal_example1.rb
|
114
|
+
- lib/neography.rb
|
115
|
+
- lib/neography/config.rb
|
116
|
+
- lib/neography/equal.rb
|
117
|
+
- lib/neography/neography.rb
|
118
|
+
- lib/neography/node.rb
|
119
|
+
- lib/neography/node_relationship.rb
|
120
|
+
- lib/neography/node_traverser.rb
|
121
|
+
- lib/neography/property.rb
|
122
|
+
- lib/neography/property_container.rb
|
123
|
+
- lib/neography/relationship.rb
|
124
|
+
- lib/neography/relationship_traverser.rb
|
125
|
+
- lib/neography/rest.rb
|
126
|
+
- lib/neography/version.rb
|
127
|
+
- neography.gemspec
|
128
|
+
- spec/integration/neography_spec.rb
|
129
|
+
- spec/integration/node_relationship_spec.rb
|
130
|
+
- spec/integration/node_spec.rb
|
131
|
+
- spec/integration/relationship_spec.rb
|
132
|
+
- spec/integration/rest_bulk_spec.rb
|
133
|
+
- spec/integration/rest_experimental_spec.rb
|
134
|
+
- spec/integration/rest_index_spec.rb
|
135
|
+
- spec/integration/rest_node_spec.rb
|
136
|
+
- spec/integration/rest_path_spec.rb
|
137
|
+
- spec/integration/rest_relationship_spec.rb
|
138
|
+
- spec/integration/rest_traverse_spec.rb
|
139
|
+
- spec/spec_helper.rb
|
140
|
+
- spec/support/fake_root_spec.rb
|
140
141
|
has_rdoc: true
|
141
142
|
homepage: http://rubygems.org/gems/neography
|
142
143
|
licenses: []
|
@@ -145,23 +146,23 @@ post_install_message:
|
|
145
146
|
rdoc_options: []
|
146
147
|
|
147
148
|
require_paths:
|
148
|
-
|
149
|
+
- lib
|
149
150
|
required_ruby_version: !ruby/object:Gem::Requirement
|
150
151
|
none: false
|
151
152
|
requirements:
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
segments:
|
156
|
+
- 0
|
157
|
+
version: "0"
|
157
158
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
159
|
none: false
|
159
160
|
requirements:
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
segments:
|
164
|
+
- 0
|
165
|
+
version: "0"
|
165
166
|
requirements: []
|
166
167
|
|
167
168
|
rubyforge_project: neography
|