neography-ajaycb 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.project +12 -0
- data/.travis.yml +1 -0
- data/CONTRIBUTORS +12 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +39 -0
- data/LICENSE +19 -0
- data/README.rdoc +350 -0
- data/Rakefile +15 -0
- data/examples/facebook.rb +40 -0
- data/examples/facebook_v2.rb +25 -0
- data/examples/greatest.rb +43 -0
- data/examples/linkedin.rb +39 -0
- data/examples/linkedin_v2.rb +22 -0
- data/examples/traversal_example1.rb +65 -0
- data/examples/traversal_example2.rb +54 -0
- data/lib/neography.rb +46 -0
- data/lib/neography/config.rb +17 -0
- data/lib/neography/equal.rb +21 -0
- data/lib/neography/index.rb +13 -0
- data/lib/neography/neography.rb +10 -0
- data/lib/neography/node.rb +45 -0
- data/lib/neography/node_path.rb +29 -0
- data/lib/neography/node_relationship.rb +35 -0
- data/lib/neography/node_traverser.rb +142 -0
- data/lib/neography/path_traverser.rb +94 -0
- data/lib/neography/property.rb +53 -0
- data/lib/neography/property_container.rb +17 -0
- data/lib/neography/railtie.rb +8 -0
- data/lib/neography/relationship.rb +68 -0
- data/lib/neography/relationship_traverser.rb +80 -0
- data/lib/neography/rest.rb +534 -0
- data/lib/neography/tasks.rb +131 -0
- data/lib/neography/version.rb +3 -0
- data/neography.gemspec +29 -0
- data/spec/integration/authorization_spec.rb +48 -0
- data/spec/integration/index_spec.rb +32 -0
- data/spec/integration/neography_spec.rb +10 -0
- data/spec/integration/node_path_spec.rb +222 -0
- data/spec/integration/node_relationship_spec.rb +374 -0
- data/spec/integration/node_spec.rb +215 -0
- data/spec/integration/relationship_spec.rb +37 -0
- data/spec/integration/rest_batch_spec.rb +221 -0
- data/spec/integration/rest_bulk_spec.rb +106 -0
- data/spec/integration/rest_experimental_spec.rb +22 -0
- data/spec/integration/rest_gremlin_fail_spec.rb +46 -0
- data/spec/integration/rest_index_spec.rb +297 -0
- data/spec/integration/rest_node_spec.rb +232 -0
- data/spec/integration/rest_path_spec.rb +209 -0
- data/spec/integration/rest_plugin_spec.rb +67 -0
- data/spec/integration/rest_relationship_spec.rb +327 -0
- data/spec/integration/rest_traverse_spec.rb +149 -0
- data/spec/spec_helper.rb +18 -0
- metadata +222 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module Neography
|
2
|
+
module NodePath
|
3
|
+
|
4
|
+
def all_paths_to(to)
|
5
|
+
PathTraverser.new(self, to, "allPaths", true)
|
6
|
+
end
|
7
|
+
|
8
|
+
def all_simple_paths_to(to)
|
9
|
+
PathTraverser.new(self, to, "allSimplePaths", true)
|
10
|
+
end
|
11
|
+
|
12
|
+
def all_shortest_paths_to(to)
|
13
|
+
PathTraverser.new(self, to, "shortestPath", true)
|
14
|
+
end
|
15
|
+
|
16
|
+
def path_to(to)
|
17
|
+
PathTraverser.new(self, to, "allPaths", false)
|
18
|
+
end
|
19
|
+
|
20
|
+
def simple_path_to(to)
|
21
|
+
PathTraverser.new(self, to, "allSimplePaths", false)
|
22
|
+
end
|
23
|
+
|
24
|
+
def shortest_path_to(to)
|
25
|
+
PathTraverser.new(self, to, "shortestPath", false)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Neography
|
2
|
+
module NodeRelationship
|
3
|
+
|
4
|
+
def outgoing(types=nil)
|
5
|
+
NodeTraverser.new(self).outgoing(types)
|
6
|
+
end
|
7
|
+
|
8
|
+
def incoming(types=nil)
|
9
|
+
NodeTraverser.new(self).incoming(types)
|
10
|
+
end
|
11
|
+
|
12
|
+
def both(types=nil)
|
13
|
+
NodeTraverser.new(self).both(types)
|
14
|
+
end
|
15
|
+
|
16
|
+
def rels(*types)
|
17
|
+
Neography::RelationshipTraverser.new(self, types, :both)
|
18
|
+
end
|
19
|
+
|
20
|
+
def rel(dir, type)
|
21
|
+
rel = Neography::RelationshipTraverser.new(self, type, dir)
|
22
|
+
rel = rel.first unless rel.nil?
|
23
|
+
rel
|
24
|
+
end
|
25
|
+
|
26
|
+
def rel?(dir=nil, type=nil)
|
27
|
+
if DIRECTIONS.include?(dir.to_s)
|
28
|
+
!self.neo_server.get_node_relationships(self, dir, type).nil?
|
29
|
+
else
|
30
|
+
!self.neo_server.get_node_relationships(self, type, dir).nil?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Neography
|
2
|
+
class NodeTraverser
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :order, :uniqueness, :depth, :prune, :filter, :relationships
|
6
|
+
|
7
|
+
def initialize(from, types = nil, dir = "all" )
|
8
|
+
@from = from
|
9
|
+
@order = "depth first"
|
10
|
+
@uniqueness = "none"
|
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 uniqueness(u)
|
52
|
+
@uniqueness = u
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def order(o)
|
57
|
+
@order = o
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
def filter(body)
|
62
|
+
@filter = Hash.new
|
63
|
+
@filter["language"] = "javascript"
|
64
|
+
@filter["body"] = body
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def prune(body)
|
69
|
+
@prune = Hash.new
|
70
|
+
@prune["language"] = "javascript"
|
71
|
+
@prune["body"] = body
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
def depth(d)
|
76
|
+
d = 2147483647 if d == :all
|
77
|
+
@depth = d
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
def include_start_node
|
82
|
+
@filter = Hash.new
|
83
|
+
@filter["language"] = "builtin"
|
84
|
+
@filter["name"] = "all"
|
85
|
+
self
|
86
|
+
end
|
87
|
+
|
88
|
+
def size
|
89
|
+
[*self].size
|
90
|
+
end
|
91
|
+
|
92
|
+
alias_method :length, :size
|
93
|
+
|
94
|
+
def [](index)
|
95
|
+
each_with_index {|node,i| break node if index == i}
|
96
|
+
end
|
97
|
+
|
98
|
+
def empty?
|
99
|
+
first == nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def each
|
103
|
+
iterator.each do |i|
|
104
|
+
node = @from.class.new(i)
|
105
|
+
node.neo_server = @from.neo_server
|
106
|
+
yield node
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def iterator
|
111
|
+
options = Hash.new
|
112
|
+
options["order"] = @order
|
113
|
+
options["uniqueness"] = @uniqueness
|
114
|
+
options["relationships"] = @relationships
|
115
|
+
options["prune evaluator"] = @prune unless @prune.nil?
|
116
|
+
options["return filter"] = @filter unless @filter.nil?
|
117
|
+
options["depth"] = @depth unless @depth.nil?
|
118
|
+
|
119
|
+
if @relationships[0]["type"].empty?
|
120
|
+
rels = @from.neo_server.get_node_relationships(@from, @relationships[0]["direction"])
|
121
|
+
case @relationships[0]["direction"]
|
122
|
+
when "in"
|
123
|
+
rels.collect { |r| @from.neo_server.get_node(r["start"]) } #.uniq
|
124
|
+
when "out"
|
125
|
+
rels.collect { |r| @from.neo_server.get_node(r["end"]) } #.uniq
|
126
|
+
else
|
127
|
+
rels.collect { |r|
|
128
|
+
if @from.neo_id == r["start"].split('/').last
|
129
|
+
@from.neo_server.get_node(r["end"])
|
130
|
+
else
|
131
|
+
@from.neo_server.get_node(r["start"])
|
132
|
+
end
|
133
|
+
} #.uniq
|
134
|
+
end
|
135
|
+
else
|
136
|
+
@from.neo_server.traverse(@from, "nodes", options)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Neography
|
2
|
+
class PathTraverser
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_accessor :depth, :algorithm, :relationships, :get
|
6
|
+
|
7
|
+
def initialize(from, to, algorithm, all=false, types = nil, dir = "all" )
|
8
|
+
@from = from
|
9
|
+
@to = to
|
10
|
+
@algorithm = algorithm
|
11
|
+
@all = all
|
12
|
+
@relationships = Array.new
|
13
|
+
types.each do |type|
|
14
|
+
@relationships << {"type" => type.to_s, "direction" => dir.to_s }
|
15
|
+
end unless types.nil?
|
16
|
+
@get = ["node","rel"]
|
17
|
+
@loaded = Array.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def nodes
|
21
|
+
@get = ["node"]
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def relationships
|
26
|
+
@get = ["rel"]
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method :rels, :relationships
|
31
|
+
|
32
|
+
def both(type)
|
33
|
+
@relationships << {"type" => type.to_s, "direction" => "all"}
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def outgoing(type)
|
38
|
+
@relationships << {"type" => type.to_s, "direction" => "out"}
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def incoming(type)
|
43
|
+
@relationships << {"type" => type.to_s, "direction" => "in"}
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def depth(d)
|
48
|
+
d = 2147483647 if d == :all
|
49
|
+
@depth = d
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def size
|
54
|
+
[*self].size
|
55
|
+
end
|
56
|
+
|
57
|
+
alias_method :length, :size
|
58
|
+
|
59
|
+
def each
|
60
|
+
iterator.each do |path|
|
61
|
+
paths = Array.new
|
62
|
+
|
63
|
+
if @get.include?("node")
|
64
|
+
path["nodes"].each_with_index do |n, i|
|
65
|
+
@loaded[n.split('/').last.to_i] = Neography::Node.load(n) if @loaded.at(n.split('/').last.to_i).nil?
|
66
|
+
paths[i * 2] = @loaded[n.split('/').last.to_i]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if @get.include?("rel")
|
71
|
+
path["relationships"].each_with_index do |r, i|
|
72
|
+
@loaded[r.split('/').last.to_i] = Neography::Relationship.load(r) if @loaded.at(r.split('/').last.to_i).nil?
|
73
|
+
paths[i * 2 + 1] = @loaded[r.split('/').last.to_i]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
yield paths.compact
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def empty?
|
82
|
+
first == nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def iterator
|
86
|
+
if @all.nil?
|
87
|
+
@from.neo_server.get_path(@from, @to, @relationships, @depth, @algorithm)
|
88
|
+
else
|
89
|
+
@from.neo_server.get_paths(@from, @to, @relationships, @depth, @algorithm)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Neography
|
2
|
+
module Property
|
3
|
+
|
4
|
+
|
5
|
+
def [](key)
|
6
|
+
return unless respond_to?(key)
|
7
|
+
@table[key]
|
8
|
+
end
|
9
|
+
|
10
|
+
def []=(key, value)
|
11
|
+
k = key.to_s
|
12
|
+
if value.nil?
|
13
|
+
if self.is_a? Neography::Node
|
14
|
+
neo_server.remove_node_properties(self.neo_id, [key])
|
15
|
+
else
|
16
|
+
neo_server.remove_relationship_properties(self.neo_id, [key])
|
17
|
+
end
|
18
|
+
else
|
19
|
+
if self.is_a? Neography::Node
|
20
|
+
neo_server.set_node_properties(self.neo_id, {k => value})
|
21
|
+
else
|
22
|
+
neo_server.set_relationship_properties(self.neo_id, {k => value})
|
23
|
+
end
|
24
|
+
new_ostruct_member(k) unless self.respond_to?(key)
|
25
|
+
end
|
26
|
+
@table[key] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def new_ostruct_member(name)
|
31
|
+
name = name.to_sym
|
32
|
+
unless self.respond_to?(name)
|
33
|
+
meta = class << self; self; end
|
34
|
+
meta.send(:define_method, name) { @table[name] }
|
35
|
+
meta.send(:define_method, "#{name}=") do |x|
|
36
|
+
@table[name] = x
|
37
|
+
self[name.to_sym] = x
|
38
|
+
end
|
39
|
+
end
|
40
|
+
name
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def self.method_missing(method_sym, *arguments, &block)
|
45
|
+
if (method_sym.to_s =~ /$=/) != nil
|
46
|
+
new_ostruct_member(method_sym.to_s.chomp("="))
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Neography
|
2
|
+
class PropertyContainer < OpenStruct
|
3
|
+
attr_reader :neo_id
|
4
|
+
|
5
|
+
def initialize(hash=nil)
|
6
|
+
@table = {}
|
7
|
+
if hash
|
8
|
+
@neo_id = hash["self"].split('/').last
|
9
|
+
for k,v in hash["data"]
|
10
|
+
@table[k.to_sym] = v
|
11
|
+
new_ostruct_member(k)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Neography
|
2
|
+
class Relationship < PropertyContainer
|
3
|
+
include Neography::Equal
|
4
|
+
include Neography::Property
|
5
|
+
extend Neography::Index
|
6
|
+
|
7
|
+
attr_accessor :start_node, :end_node, :rel_type
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def create(type, from_node, to_node, props=nil)
|
12
|
+
rel = Neography::Relationship.new(from_node.neo_server.create_relationship(type, from_node, to_node, props))
|
13
|
+
rel.start_node = from_node
|
14
|
+
rel.end_node = to_node
|
15
|
+
rel.rel_type = type
|
16
|
+
rel
|
17
|
+
end
|
18
|
+
|
19
|
+
def load(*args)
|
20
|
+
# the first argument can be an hash of properties to set
|
21
|
+
rel = !args[0].is_a?(Neography::Rest) && args[0] || args[1]
|
22
|
+
|
23
|
+
# a db instance can be given, it is the first argument or the second
|
24
|
+
db = (args[0].is_a?(Neography::Rest) && args[0]) || args[1] || Neography::Rest.new
|
25
|
+
rel = db.get_relationship(rel)
|
26
|
+
unless rel.nil?
|
27
|
+
rel = Neography::Relationship.new(rel)
|
28
|
+
rel.start_node = Neography::Node.load(rel.start_node, db)
|
29
|
+
rel.end_node = Neography::Node.load(rel.end_node, db)
|
30
|
+
end
|
31
|
+
rel
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(hash=nil, server=nil)
|
36
|
+
super(hash)
|
37
|
+
@start_node = hash["start"].split('/').last
|
38
|
+
@end_node = hash["end"].split('/').last
|
39
|
+
@rel_type = hash["type"]
|
40
|
+
neo_server = server
|
41
|
+
end
|
42
|
+
|
43
|
+
def neo_server
|
44
|
+
@neo_server ||= self.start_node.neo_server
|
45
|
+
end
|
46
|
+
|
47
|
+
def neo_server=(server)
|
48
|
+
@neo_server = server
|
49
|
+
end
|
50
|
+
|
51
|
+
def del
|
52
|
+
self.start_node.neo_server.delete_relationship(self.neo_id)
|
53
|
+
end
|
54
|
+
|
55
|
+
def exist?
|
56
|
+
!self.start_node.neo_server.get_relationship(self.neo_id).nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
def other_node(node)
|
60
|
+
if node == @start_node
|
61
|
+
@end_node
|
62
|
+
else
|
63
|
+
@start_node
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|