neography 0.0.1 → 0.0.2
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/README.rdoc +32 -6
- data/lib/neography/rest.rb +54 -0
- data/lib/neography/version.rb +1 -1
- data/spec/integration/rest_path_spec.rb +206 -12
- data/spec/integration/rest_traverse_spec.rb +230 -0
- metadata +3 -3
- data/lib/neography/config.rb +0 -152
data/README.rdoc
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
== Welcome to Neography
|
2
2
|
|
3
|
-
Neography is a thin
|
3
|
+
Neography is a thin Ruby wrapper to the Neo4j Rest API, for more information:
|
4
4
|
* {Getting Started with Neo4j Server}[http://wiki.neo4j.org/content/Getting_Started_with_Neo4j_Server]
|
5
5
|
* {Neo4j Rest API Reference}[http://components.neo4j.org/neo4j-rest/]
|
6
6
|
|
7
|
+
If you want to the full power of Neo4j, you will want to use JRuby and the excellent Neo4j.rb gem at https://github.com/andreasronge/neo4j
|
7
8
|
|
8
9
|
=== Installation
|
9
10
|
|
@@ -78,17 +79,42 @@ To Use:
|
|
78
79
|
@neo.get_path(from, to, relationships, depth=4, algorithm="shortestPath") # finds the shortest path between two nodes
|
79
80
|
@neo.get_paths(from, to, relationships, depth=3, algorithm="allPaths") # finds all paths between two nodes
|
80
81
|
|
82
|
+
nodes = @neo.traverse(id, # the id of the node where the traversal starts
|
83
|
+
"nodes", # return_type (can be "nodes", "relationships" or "paths"
|
84
|
+
{"order" => "breadth first", # "breadth first" or "depth first" traversal order
|
85
|
+
"uniqueness" => "node global", # See Uniqueness in API documentation for options.
|
86
|
+
"relationships" => [{"type"=> "roommates", # A hash containg a description of the traversal
|
87
|
+
"direction" => "all"}, # two relationships.
|
88
|
+
{"type"=> "friends", #
|
89
|
+
"direction" => "out"}], #
|
90
|
+
"prune evaluator" => {"language" => "javascript", # A prune evaluator (when to stop traversing)
|
91
|
+
"body" => "position.endNode().getProperty('age') < 21;"
|
92
|
+
"return filter" => {"language" => "builtin", # "all" or "all but start node"
|
93
|
+
"name" => "all"},
|
94
|
+
"depth" => 4})
|
95
|
+
|
96
|
+
# "depth" is a short-hand way of specifying a prune evaluator which prunes after a certain depth.
|
97
|
+
# If not specified a depth of 1 is used and if a "prune evaluator" is specified instead of a depth, no depth limit is set.
|
98
|
+
|
99
|
+
Please see the specs for more examples.
|
100
|
+
|
101
|
+
See Neo4j API for:
|
102
|
+
* {Order}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/graphdb/Traverser.Order.html]
|
103
|
+
* {Uniqueness}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/kernel/Uniqueness.html]
|
104
|
+
* {Prune Evaluator}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/graphdb/StopEvaluator.html]
|
105
|
+
* {Return Filter}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/graphdb/ReturnableEvaluator.html]
|
106
|
+
|
81
107
|
=== To Do
|
82
108
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
109
|
+
* More tests
|
110
|
+
* examples
|
111
|
+
* batch import with typhoeus ?
|
112
|
+
* create proper objects for Node and Relationship
|
87
113
|
|
88
114
|
=== License
|
89
115
|
|
90
116
|
* Neography - MIT, see the LICENSE file http://github.com/maxdemarzi/neography/tree/master/LICENSE.
|
91
117
|
* Lucene - Apache, see http://lucene.apache.org/java/docs/features.html
|
92
|
-
* Neo4j - Dual free software/commercial license, see http://neo4j.org
|
118
|
+
* Neo4j - Dual free software/commercial license, see http://neo4j.org
|
93
119
|
|
94
120
|
|
data/lib/neography/rest.rb
CHANGED
@@ -161,6 +161,16 @@ module Neography
|
|
161
161
|
index
|
162
162
|
end
|
163
163
|
|
164
|
+
def traverse(id, return_type, description)
|
165
|
+
options = { :body => {"order" => get_order(description["order"]),
|
166
|
+
"uniqueness" => get_uniqueness(description["uniqueness"]),
|
167
|
+
"relationships" => description["relationships"],
|
168
|
+
"prune evaluator" => description["prune evaluator"],
|
169
|
+
"return filter" => description["return filter"],
|
170
|
+
"max depth" => get_depth(description["depth"]), }.to_json, :headers => {'Content-Type' => 'application/json'} }
|
171
|
+
traversal = post("/node/#{id}/traverse/#{get_type(return_type)}", options) || Array.new
|
172
|
+
end
|
173
|
+
|
164
174
|
def get_path(from, to, relationships, depth=1, algorithm="shortestPath")
|
165
175
|
options = { :body => {"to" => self.configuration + "/node/#{to}", "relationships" => relationships, "max depth" => depth, "algorithm" => get_algorithm(algorithm) }.to_json, :headers => {'Content-Type' => 'application/json'} }
|
166
176
|
path = post("/node/#{from}/path", options) || Hash.new
|
@@ -237,5 +247,49 @@ module Neography
|
|
237
247
|
end
|
238
248
|
end
|
239
249
|
|
250
|
+
def get_order(order)
|
251
|
+
case order
|
252
|
+
when :breadth, "breadth", "breadth first", "breadthFirst", :wide, "wide"
|
253
|
+
"breadth first"
|
254
|
+
else
|
255
|
+
"depth first"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def get_type(type)
|
260
|
+
case type
|
261
|
+
when :node, "nodes", :nodes, "nodes"
|
262
|
+
"node"
|
263
|
+
when :relationship, "relationship", :relationships, "relationships"
|
264
|
+
"relationship"
|
265
|
+
else
|
266
|
+
"path"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def get_uniqueness(uniqueness)
|
271
|
+
case uniqueness
|
272
|
+
when :nodeglobal, "node global", "nodeglobal", "node_global"
|
273
|
+
"node global"
|
274
|
+
when :nodepath, "node path", "nodepath", "node_path"
|
275
|
+
"node path"
|
276
|
+
when :noderecent, "node recent", "noderecent", "node_recent"
|
277
|
+
"node recent"
|
278
|
+
when :relationshipglobal, "relationship global", "relationshipglobal", "relationship_global"
|
279
|
+
"relationship global"
|
280
|
+
when :relationshippath, "relationship path", "relationshippath", "relationship_path"
|
281
|
+
"relationship path"
|
282
|
+
when :relationshiprecent, "relationship recent", "relationshiprecent", "relationship_recent"
|
283
|
+
"relationship recent"
|
284
|
+
else
|
285
|
+
"none"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def get_depth(depth)
|
290
|
+
return 1 if depth.to_i == 0
|
291
|
+
depth.to_i
|
292
|
+
end
|
293
|
+
|
240
294
|
end
|
241
295
|
end
|
data/lib/neography/version.rb
CHANGED
@@ -19,41 +19,235 @@ describe Neography::Rest do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "can get the shortest path between two nodes" do
|
22
|
-
|
22
|
+
new_node1 = @neo.create_node
|
23
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
24
|
+
new_node2 = @neo.create_node
|
25
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
26
|
+
new_node3 = @neo.create_node
|
27
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
28
|
+
new_node4 = @neo.create_node
|
29
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
30
|
+
new_node5 = @neo.create_node
|
31
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
32
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
33
|
+
@neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
34
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
35
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
36
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
37
|
+
path = @neo.get_path(new_node1[:id], new_node5[:id], {"type"=> "friends", "direction" => "out"}, depth=3, algorithm="shortestPath")
|
38
|
+
path["start"].should == new_node1["self"]
|
39
|
+
path["end"].should == new_node5["self"]
|
40
|
+
path["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node5["self"]]
|
23
41
|
end
|
24
42
|
|
25
43
|
it "can get a simple path between two nodes" do
|
26
|
-
|
44
|
+
new_node1 = @neo.create_node
|
45
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
46
|
+
new_node2 = @neo.create_node
|
47
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
48
|
+
new_node3 = @neo.create_node
|
49
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
50
|
+
new_node4 = @neo.create_node
|
51
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
52
|
+
new_node5 = @neo.create_node
|
53
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
54
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
55
|
+
@neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
56
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
57
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
58
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
59
|
+
path = @neo.get_path(new_node1[:id], new_node5[:id], {"type"=> "friends", "direction" => "out"}, depth=3, algorithm="simplePaths")
|
60
|
+
path["start"].should == new_node1["self"]
|
61
|
+
path["end"].should == new_node5["self"]
|
62
|
+
path["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node5["self"]]
|
27
63
|
end
|
28
64
|
|
29
|
-
it "
|
30
|
-
|
65
|
+
it "fails to get a path between two nodes 3 nodes apart when using max depth of 2" do
|
66
|
+
new_node1 = @neo.create_node
|
67
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
68
|
+
new_node2 = @neo.create_node
|
69
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
70
|
+
new_node3 = @neo.create_node
|
71
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
72
|
+
new_node4 = @neo.create_node
|
73
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
74
|
+
new_node5 = @neo.create_node
|
75
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
76
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
77
|
+
@neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
78
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
79
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
80
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
81
|
+
path = @neo.get_path(new_node1[:id], new_node5[:id], {"type"=> "friends", "direction" => "out"}, depth=2, algorithm="shortestPath")
|
82
|
+
path["start"].should be_nil
|
83
|
+
path["end"].should be_nil
|
31
84
|
end
|
32
85
|
|
33
86
|
it "can get a path between two nodes of a specific relationship" do
|
34
|
-
|
87
|
+
new_node1 = @neo.create_node
|
88
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
89
|
+
new_node2 = @neo.create_node
|
90
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
91
|
+
new_node3 = @neo.create_node
|
92
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
93
|
+
new_node4 = @neo.create_node
|
94
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
95
|
+
new_node5 = @neo.create_node
|
96
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
97
|
+
@neo.create_relationship("classmates", new_node1[:id], new_node2[:id])
|
98
|
+
@neo.create_relationship("classmates", new_node2[:id], new_node5[:id])
|
99
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
100
|
+
@neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
101
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
102
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
103
|
+
path = @neo.get_path(new_node1[:id], new_node5[:id], {"type"=> "friends", "direction" => "out"}, depth=4, algorithm="shortestPath")
|
104
|
+
path["start"].should == new_node1["self"]
|
105
|
+
path["end"].should == new_node5["self"]
|
106
|
+
path["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node4["self"], new_node5["self"]]
|
35
107
|
end
|
36
108
|
end
|
37
109
|
|
38
110
|
describe "get paths" do
|
39
111
|
it "can get the shortest paths between two nodes" do
|
40
|
-
|
112
|
+
new_node1 = @neo.create_node
|
113
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
114
|
+
new_node2 = @neo.create_node
|
115
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
116
|
+
new_node3 = @neo.create_node
|
117
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
118
|
+
new_node4 = @neo.create_node
|
119
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
120
|
+
new_node5 = @neo.create_node
|
121
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
122
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
123
|
+
@neo.create_relationship("friends", new_node2[:id], new_node5[:id])
|
124
|
+
@neo.create_relationship("friends", new_node1[:id], new_node3[:id])
|
125
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
126
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
127
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
128
|
+
paths = @neo.get_paths(new_node1[:id], new_node5[:id], {"type"=> "friends", "direction" => "out"}, depth=4, algorithm="shortestPath")
|
129
|
+
paths.length.should == 2
|
130
|
+
paths[0]["length"].should == 2
|
131
|
+
paths[0]["start"].should == new_node1["self"]
|
132
|
+
paths[0]["end"].should == new_node5["self"]
|
133
|
+
paths[1]["length"].should == 2
|
134
|
+
paths[1]["start"].should == new_node1["self"]
|
135
|
+
paths[1]["end"].should == new_node5["self"]
|
41
136
|
end
|
42
137
|
|
43
138
|
it "can get all paths between two nodes" do
|
44
|
-
|
139
|
+
new_node1 = @neo.create_node
|
140
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
141
|
+
new_node2 = @neo.create_node
|
142
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
143
|
+
new_node3 = @neo.create_node
|
144
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
145
|
+
new_node4 = @neo.create_node
|
146
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
147
|
+
new_node5 = @neo.create_node
|
148
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
149
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
150
|
+
@neo.create_relationship("friends", new_node2[:id], new_node5[:id])
|
151
|
+
@neo.create_relationship("friends", new_node1[:id], new_node3[:id])
|
152
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
153
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
154
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
155
|
+
paths = @neo.get_paths(new_node1[:id], new_node5[:id], {"type"=> "friends", "direction" => "out"}, depth=4, algorithm="allPaths")
|
156
|
+
paths.length.should == 3
|
157
|
+
paths[0]["length"].should == 2
|
158
|
+
paths[0]["start"].should == new_node1["self"]
|
159
|
+
paths[0]["end"].should == new_node5["self"]
|
160
|
+
paths[1]["length"].should == 3
|
161
|
+
paths[1]["start"].should == new_node1["self"]
|
162
|
+
paths[1]["end"].should == new_node5["self"]
|
163
|
+
paths[2]["length"].should == 2
|
164
|
+
paths[2]["start"].should == new_node1["self"]
|
165
|
+
paths[2]["end"].should == new_node5["self"]
|
45
166
|
end
|
46
167
|
|
47
168
|
it "can get all simple paths between two nodes" do
|
48
|
-
|
169
|
+
new_node1 = @neo.create_node
|
170
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
171
|
+
new_node2 = @neo.create_node
|
172
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
173
|
+
new_node3 = @neo.create_node
|
174
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
175
|
+
new_node4 = @neo.create_node
|
176
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
177
|
+
new_node5 = @neo.create_node
|
178
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
179
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
180
|
+
@neo.create_relationship("friends", new_node2[:id], new_node1[:id])
|
181
|
+
@neo.create_relationship("friends", new_node2[:id], new_node5[:id])
|
182
|
+
@neo.create_relationship("friends", new_node1[:id], new_node3[:id])
|
183
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
184
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
185
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
186
|
+
paths = @neo.get_paths(new_node1[:id], new_node5[:id], {"type"=> "friends", "direction" => "out"}, depth=4, algorithm="allSimplePaths")
|
187
|
+
paths.length.should == 3
|
188
|
+
paths[0]["length"].should == 2
|
189
|
+
paths[0]["start"].should == new_node1["self"]
|
190
|
+
paths[0]["end"].should == new_node5["self"]
|
191
|
+
paths[1]["length"].should == 3
|
192
|
+
paths[1]["start"].should == new_node1["self"]
|
193
|
+
paths[1]["end"].should == new_node5["self"]
|
194
|
+
paths[2]["length"].should == 2
|
195
|
+
paths[2]["start"].should == new_node1["self"]
|
196
|
+
paths[2]["end"].should == new_node5["self"]
|
49
197
|
end
|
50
198
|
|
51
|
-
it "can get paths between two nodes of max depth
|
52
|
-
|
53
|
-
|
199
|
+
it "can get paths between two nodes of max depth 2" do
|
200
|
+
new_node1 = @neo.create_node
|
201
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
202
|
+
new_node2 = @neo.create_node
|
203
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
204
|
+
new_node3 = @neo.create_node
|
205
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
206
|
+
new_node4 = @neo.create_node
|
207
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
208
|
+
new_node5 = @neo.create_node
|
209
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
210
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
211
|
+
@neo.create_relationship("friends", new_node2[:id], new_node5[:id])
|
212
|
+
@neo.create_relationship("friends", new_node1[:id], new_node3[:id])
|
213
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
214
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
215
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
216
|
+
paths = @neo.get_paths(new_node1[:id], new_node5[:id], {"type"=> "friends", "direction" => "out"}, depth=2, algorithm="allPaths")
|
217
|
+
paths.length.should == 2
|
218
|
+
paths[0]["length"].should == 2
|
219
|
+
paths[0]["start"].should == new_node1["self"]
|
220
|
+
paths[0]["end"].should == new_node5["self"]
|
221
|
+
paths[1]["length"].should == 2
|
222
|
+
paths[1]["start"].should == new_node1["self"]
|
223
|
+
paths[1]["end"].should == new_node5["self"] end
|
54
224
|
|
55
225
|
it "can get paths between two nodes of a specific relationship" do
|
56
|
-
|
226
|
+
new_node1 = @neo.create_node
|
227
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
228
|
+
new_node2 = @neo.create_node
|
229
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
230
|
+
new_node3 = @neo.create_node
|
231
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
232
|
+
new_node4 = @neo.create_node
|
233
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
234
|
+
new_node5 = @neo.create_node
|
235
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
236
|
+
@neo.create_relationship("classmates", new_node1[:id], new_node2[:id])
|
237
|
+
@neo.create_relationship("classmates", new_node2[:id], new_node5[:id])
|
238
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
239
|
+
@neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
240
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
241
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
242
|
+
@neo.create_relationship("classmates", new_node1[:id], new_node3[:id])
|
243
|
+
@neo.create_relationship("classmates", new_node3[:id], new_node5[:id])
|
244
|
+
paths = @neo.get_paths(new_node1[:id], new_node5[:id], {"type"=> "classmates", "direction" => "out"}, depth=4, algorithm="allPaths")
|
245
|
+
paths[0]["length"].should == 2
|
246
|
+
paths[0]["start"].should == new_node1["self"]
|
247
|
+
paths[0]["end"].should == new_node5["self"]
|
248
|
+
paths[1]["length"].should == 2
|
249
|
+
paths[1]["start"].should == new_node1["self"]
|
250
|
+
paths[1]["end"].should == new_node5["self"]
|
57
251
|
end
|
58
252
|
|
59
253
|
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
|
3
|
+
describe Neography::Rest do
|
4
|
+
before(:each) do
|
5
|
+
@neo = Neography::Rest.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "traverse" do
|
9
|
+
it "can traverse the graph and return nodes" do
|
10
|
+
new_node1 = @neo.create_node
|
11
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
12
|
+
new_node2 = @neo.create_node
|
13
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
14
|
+
new_node3 = @neo.create_node
|
15
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
16
|
+
new_node4 = @neo.create_node
|
17
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
18
|
+
new_node5 = @neo.create_node
|
19
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
20
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
21
|
+
@neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
22
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
23
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
24
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
25
|
+
nodes = @neo.traverse(new_node1[:id], "nodes", {"relationships" => {"type"=> "friends", "direction" => "out"}, "depth" => 4} )
|
26
|
+
nodes.should_not be_nil
|
27
|
+
nodes[0]["self"].should == new_node2["self"]
|
28
|
+
nodes[1]["self"].should == new_node3["self"]
|
29
|
+
nodes[2]["self"].should == new_node4["self"]
|
30
|
+
nodes[3]["self"].should == new_node5["self"]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can traverse the graph and return relationships" do
|
34
|
+
new_node1 = @neo.create_node
|
35
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
36
|
+
new_node2 = @neo.create_node
|
37
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
38
|
+
new_node3 = @neo.create_node
|
39
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
40
|
+
new_node4 = @neo.create_node
|
41
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
42
|
+
new_node5 = @neo.create_node
|
43
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
44
|
+
|
45
|
+
new_relationship1= @neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
46
|
+
new_relationship2= @neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
47
|
+
new_relationship3= @neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
48
|
+
new_relationship4= @neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
49
|
+
new_relationship5= @neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
50
|
+
|
51
|
+
relationships = @neo.traverse(new_node1[:id], "relationships", {"relationships" => {"type"=> "friends", "direction" => "out"}, "depth" => 4} )
|
52
|
+
relationships.should_not be_nil
|
53
|
+
|
54
|
+
relationships[0]["self"].should == new_relationship1["self"]
|
55
|
+
relationships[1]["self"].should == new_relationship2["self"]
|
56
|
+
relationships[2]["self"].should == new_relationship3["self"]
|
57
|
+
relationships[3]["self"].should == new_relationship4["self"]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "can traverse the graph and return paths" do
|
61
|
+
new_node1 = @neo.create_node
|
62
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
63
|
+
new_node2 = @neo.create_node
|
64
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
65
|
+
new_node3 = @neo.create_node
|
66
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
67
|
+
new_node4 = @neo.create_node
|
68
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
69
|
+
new_node5 = @neo.create_node
|
70
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
71
|
+
|
72
|
+
new_relationship1= @neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
73
|
+
new_relationship2= @neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
74
|
+
new_relationship3= @neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
75
|
+
new_relationship4= @neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
76
|
+
new_relationship5= @neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
77
|
+
|
78
|
+
paths = @neo.traverse(new_node1[:id], "paths", {"relationships" => {"type"=> "friends", "direction" => "out"}, "depth" => 4} )
|
79
|
+
paths.should_not be_nil
|
80
|
+
|
81
|
+
paths[0]["nodes"].should == [new_node1["self"], new_node2["self"]]
|
82
|
+
paths[1]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"]]
|
83
|
+
paths[2]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node4["self"]]
|
84
|
+
paths[3]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node4["self"], new_node5["self"]]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "can traverse the graph up to a certain depth" do
|
88
|
+
new_node1 = @neo.create_node
|
89
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
90
|
+
new_node2 = @neo.create_node
|
91
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
92
|
+
new_node3 = @neo.create_node
|
93
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
94
|
+
new_node4 = @neo.create_node
|
95
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
96
|
+
new_node5 = @neo.create_node
|
97
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
98
|
+
|
99
|
+
new_relationship1= @neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
100
|
+
new_relationship2= @neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
101
|
+
new_relationship3= @neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
102
|
+
new_relationship4= @neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
103
|
+
new_relationship5= @neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
104
|
+
|
105
|
+
paths = @neo.traverse(new_node1[:id], "paths", {"relationships" => {"type"=> "friends", "direction" => "out"}, "depth" => 3} )
|
106
|
+
paths.should_not be_nil
|
107
|
+
|
108
|
+
paths[0]["nodes"].should == [new_node1["self"], new_node2["self"]]
|
109
|
+
paths[1]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"]]
|
110
|
+
paths[2]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node4["self"]]
|
111
|
+
paths[3]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node5["self"]]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "can traverse the graph in a certain order" do
|
115
|
+
new_node1 = @neo.create_node
|
116
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
117
|
+
new_node2 = @neo.create_node
|
118
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
119
|
+
new_node3 = @neo.create_node
|
120
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
121
|
+
new_node4 = @neo.create_node
|
122
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
123
|
+
new_node5 = @neo.create_node
|
124
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
125
|
+
|
126
|
+
new_relationship1= @neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
127
|
+
new_relationship2= @neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
128
|
+
new_relationship3= @neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
129
|
+
new_relationship4= @neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
130
|
+
new_relationship5= @neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
131
|
+
|
132
|
+
paths = @neo.traverse(new_node1[:id], "paths", {"order" => "breadth first", "relationships" => {"type"=> "friends", "direction" => "out"}, "depth" => 4} )
|
133
|
+
paths.should_not be_nil
|
134
|
+
|
135
|
+
paths[0]["nodes"].should == [new_node1["self"], new_node2["self"]]
|
136
|
+
paths[1]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"]]
|
137
|
+
paths[2]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node4["self"]]
|
138
|
+
paths[3]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node5["self"]]
|
139
|
+
end
|
140
|
+
|
141
|
+
it "can traverse the graph with a specific uniqueness" do
|
142
|
+
new_node1 = @neo.create_node
|
143
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
144
|
+
new_node2 = @neo.create_node
|
145
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
146
|
+
new_node3 = @neo.create_node
|
147
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
148
|
+
new_node4 = @neo.create_node
|
149
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
150
|
+
new_node5 = @neo.create_node
|
151
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
152
|
+
|
153
|
+
new_relationship1= @neo.create_relationship("roommates", new_node1[:id], new_node2[:id])
|
154
|
+
new_relationship2= @neo.create_relationship("roommates", new_node2[:id], new_node3[:id])
|
155
|
+
new_relationship1= @neo.create_relationship("friends", new_node3[:id], new_node2[:id])
|
156
|
+
new_relationship2= @neo.create_relationship("friends", new_node2[:id], new_node5[:id])
|
157
|
+
new_relationship3= @neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
158
|
+
new_relationship4= @neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
159
|
+
new_relationship5= @neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
160
|
+
|
161
|
+
paths = @neo.traverse(new_node1[:id], "paths", {"order" => "breadth first", "uniqueness" => "node global", "relationships" => [{"type"=> "roommates", "direction" => "all"},{"type"=> "friends", "direction" => "out"}], "depth" => 4} )
|
162
|
+
paths.should_not be_nil
|
163
|
+
|
164
|
+
paths[0]["nodes"].should == [new_node1["self"], new_node2["self"]]
|
165
|
+
paths[1]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"]]
|
166
|
+
paths[2]["nodes"].should == [new_node1["self"], new_node2["self"], new_node5["self"]]
|
167
|
+
paths[3]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"], new_node4["self"]]
|
168
|
+
end
|
169
|
+
|
170
|
+
it "can traverse the graph with a prune evaluator" do
|
171
|
+
new_node1 = @neo.create_node("age" => 31, "name" => "Max")
|
172
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
173
|
+
new_node2 = @neo.create_node("age" => 30, "name" => "Helene")
|
174
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
175
|
+
new_node3 = @neo.create_node("age" => 17, "name" => "Alex")
|
176
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
177
|
+
new_node4 = @neo.create_node("age" => 24, "name" => "Eric")
|
178
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
179
|
+
new_node5 = @neo.create_node("age" => 32, "name" => "Leslie")
|
180
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
181
|
+
|
182
|
+
new_relationship1= @neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
183
|
+
new_relationship2= @neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
184
|
+
new_relationship3= @neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
185
|
+
new_relationship4= @neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
186
|
+
new_relationship5= @neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
187
|
+
|
188
|
+
paths = @neo.traverse(new_node1[:id],
|
189
|
+
"paths",
|
190
|
+
{"relationships" => {"type"=> "friends", "direction" => "out"},
|
191
|
+
"depth" => 3,
|
192
|
+
"prune evaluator" => {"language" => "javascript", "body" => "position.endNode().getProperty('age') < 21;"
|
193
|
+
}} )
|
194
|
+
paths.should_not be_nil
|
195
|
+
paths[0]["nodes"].should == [new_node1["self"], new_node2["self"]]
|
196
|
+
paths[1]["nodes"].should == [new_node1["self"], new_node2["self"], new_node3["self"]]
|
197
|
+
paths[2].should be_nil
|
198
|
+
end
|
199
|
+
|
200
|
+
it "can traverse the graph with a return filter" do
|
201
|
+
new_node1 = @neo.create_node
|
202
|
+
new_node1[:id] = new_node1["self"].split('/').last
|
203
|
+
new_node2 = @neo.create_node
|
204
|
+
new_node2[:id] = new_node2["self"].split('/').last
|
205
|
+
new_node3 = @neo.create_node
|
206
|
+
new_node3[:id] = new_node3["self"].split('/').last
|
207
|
+
new_node4 = @neo.create_node
|
208
|
+
new_node4[:id] = new_node4["self"].split('/').last
|
209
|
+
new_node5 = @neo.create_node
|
210
|
+
new_node5[:id] = new_node5["self"].split('/').last
|
211
|
+
@neo.create_relationship("friends", new_node1[:id], new_node2[:id])
|
212
|
+
@neo.create_relationship("friends", new_node2[:id], new_node3[:id])
|
213
|
+
@neo.create_relationship("friends", new_node3[:id], new_node4[:id])
|
214
|
+
@neo.create_relationship("friends", new_node4[:id], new_node5[:id])
|
215
|
+
@neo.create_relationship("friends", new_node3[:id], new_node5[:id])
|
216
|
+
nodes = @neo.traverse(new_node1[:id], "nodes", {"relationships" => {"type"=> "friends", "direction" => "out"},
|
217
|
+
"return filter" => {"language" => "builtin", "name" => "all"},
|
218
|
+
"depth" => 4} )
|
219
|
+
nodes.should_not be_nil
|
220
|
+
nodes[0]["self"].should == new_node1["self"]
|
221
|
+
nodes[1]["self"].should == new_node2["self"]
|
222
|
+
nodes[2]["self"].should == new_node3["self"]
|
223
|
+
nodes[3]["self"].should == new_node4["self"]
|
224
|
+
nodes[4]["self"].should == new_node5["self"]
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Max De Marzi
|
@@ -108,7 +108,6 @@ files:
|
|
108
108
|
- README.rdoc
|
109
109
|
- Rakefile
|
110
110
|
- lib/neography.rb
|
111
|
-
- lib/neography/config.rb
|
112
111
|
- lib/neography/rest.rb
|
113
112
|
- lib/neography/version.rb
|
114
113
|
- neography.gemspec
|
@@ -116,6 +115,7 @@ files:
|
|
116
115
|
- spec/integration/rest_node_spec.rb
|
117
116
|
- spec/integration/rest_path_spec.rb
|
118
117
|
- spec/integration/rest_relationship_spec.rb
|
118
|
+
- spec/integration/rest_traverse_spec.rb
|
119
119
|
- spec/spec_helper.rb
|
120
120
|
- spec/support/fake_root_spec.rb
|
121
121
|
has_rdoc: true
|
data/lib/neography/config.rb
DELETED
@@ -1,152 +0,0 @@
|
|
1
|
-
module Neography
|
2
|
-
|
3
|
-
# == Keeps configuration for neography
|
4
|
-
#
|
5
|
-
# The most important configuration options are <tt>Neograophy::Config[:server]</tt> and <tt>Neograophy::Config[:port]</tt> which are
|
6
|
-
# used to locate where the neo4j database and is stored on the network.
|
7
|
-
# If these options are not supplied then the default of localhost:9999 will be used.
|
8
|
-
#
|
9
|
-
# ==== Default Configurations
|
10
|
-
# <tt>:protocol</tt>:: default <tt>http://</tt> protocol to use (can be https://)
|
11
|
-
# <tt>:server</tt>:: default <tt>localhost</tt> where the database is stored on the network
|
12
|
-
# <tt>:port</tt>:: default <tt>7474</tt> what port is listening
|
13
|
-
#
|
14
|
-
class Config
|
15
|
-
# This code is copied from merb-core/config.rb.
|
16
|
-
class << self
|
17
|
-
# Returns the hash of default config values for neography
|
18
|
-
#
|
19
|
-
# ==== Returns
|
20
|
-
# Hash:: The defaults for the config.
|
21
|
-
def defaults
|
22
|
-
@defaults ||= {
|
23
|
-
:protocol => 'http://',
|
24
|
-
:server => 'localhost',
|
25
|
-
:port => '7474'
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
# Yields the configuration.
|
31
|
-
#
|
32
|
-
# ==== Block parameters
|
33
|
-
# c :: The configuration parameters, a hash.
|
34
|
-
#
|
35
|
-
# ==== Examples
|
36
|
-
# Neography::Config.use do |config|
|
37
|
-
# config[:server] = '192.168.1.13'
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# ==== Returns
|
41
|
-
# nil
|
42
|
-
def use
|
43
|
-
@configuration ||= {}
|
44
|
-
yield @configuration
|
45
|
-
nil
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
|
-
# Set the value of a config entry.
|
50
|
-
#
|
51
|
-
# ==== Parameters
|
52
|
-
# key :: The key to set the parameter for.
|
53
|
-
# val :: The value of the parameter.
|
54
|
-
#
|
55
|
-
def []=(key, val)
|
56
|
-
(@configuration ||= setup)[key] = val
|
57
|
-
end
|
58
|
-
|
59
|
-
|
60
|
-
# Gets the the value of a config entry
|
61
|
-
#
|
62
|
-
# ==== Parameters
|
63
|
-
# key:: The key of the config entry value we want
|
64
|
-
#
|
65
|
-
def [](key)
|
66
|
-
(@configuration ||= setup)[key]
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
# Remove the value of a config entry.
|
71
|
-
#
|
72
|
-
# ==== Parameters
|
73
|
-
# key<Object>:: The key of the parameter to delete.
|
74
|
-
#
|
75
|
-
# ==== Returns
|
76
|
-
# The value of the removed entry.
|
77
|
-
#
|
78
|
-
def delete(key)
|
79
|
-
@configuration.delete(key)
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
# Remove all configuration. This can be useful for testing purpose.
|
84
|
-
#
|
85
|
-
#
|
86
|
-
# ==== Returns
|
87
|
-
# nil
|
88
|
-
#
|
89
|
-
def delete_all
|
90
|
-
@configuration = nil
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
# Retrieve the value of a config entry, returning the provided default if the key is not present
|
95
|
-
#
|
96
|
-
# ==== Parameters
|
97
|
-
# key:: The key to retrieve the parameter for.
|
98
|
-
# default::The default value to return if the parameter is not set.
|
99
|
-
#
|
100
|
-
# ==== Returns
|
101
|
-
# The value of the configuration parameter or the default.
|
102
|
-
#
|
103
|
-
def fetch(key, default)
|
104
|
-
@configuration.fetch(key, default)
|
105
|
-
end
|
106
|
-
|
107
|
-
# Sets up the configuration
|
108
|
-
#
|
109
|
-
# ==== Returns
|
110
|
-
# The configuration as a hash.
|
111
|
-
#
|
112
|
-
def setup()
|
113
|
-
@configuration = {}
|
114
|
-
@configuration.merge!(defaults)
|
115
|
-
@configuration
|
116
|
-
end
|
117
|
-
|
118
|
-
|
119
|
-
# Returns the configuration as a hash.
|
120
|
-
#
|
121
|
-
# ==== Returns
|
122
|
-
# The config as a hash.
|
123
|
-
#
|
124
|
-
def to_hash
|
125
|
-
@configuration
|
126
|
-
end
|
127
|
-
|
128
|
-
# Returns the config as YAML.
|
129
|
-
#
|
130
|
-
# ==== Returns
|
131
|
-
# The config as YAML.
|
132
|
-
#
|
133
|
-
def to_yaml
|
134
|
-
require "yaml"
|
135
|
-
@configuration.to_yaml
|
136
|
-
end
|
137
|
-
|
138
|
-
# Returns the configuration as a string.
|
139
|
-
#
|
140
|
-
# ==== Returns
|
141
|
-
# The config as a string.
|
142
|
-
#
|
143
|
-
def to_s
|
144
|
-
setup
|
145
|
-
@configuration[:protocol] + @configuration[:server].to_s + ':' + @configuration[:port].to_s
|
146
|
-
end
|
147
|
-
|
148
|
-
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|