neography-ajaycb 0.0.21
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/.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
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'neography/tasks'
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
8
|
+
t.rspec_opts = "--color"
|
9
|
+
t.pattern = "spec/integration/*_spec.rb"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Run Tests"
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'neography'
|
3
|
+
|
4
|
+
@neo = Neography::Rest.new
|
5
|
+
|
6
|
+
def create_person(name)
|
7
|
+
@neo.create_node("name" => name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def make_mutual_friends(node1, node2)
|
11
|
+
@neo.create_relationship("friends", node1, node2)
|
12
|
+
@neo.create_relationship("friends", node2, node1)
|
13
|
+
end
|
14
|
+
|
15
|
+
def suggestions_for(node)
|
16
|
+
@neo.traverse(node,"nodes", {"order" => "breadth first",
|
17
|
+
"uniqueness" => "node global",
|
18
|
+
"relationships" => {"type"=> "friends", "direction" => "in"},
|
19
|
+
"return filter" => {
|
20
|
+
"language" => "javascript",
|
21
|
+
"body" => "position.length() == 2;"},
|
22
|
+
"depth" => 2})
|
23
|
+
end
|
24
|
+
|
25
|
+
johnathan = create_person('Johnathan')
|
26
|
+
mark = create_person('Mark')
|
27
|
+
phill = create_person('Phill')
|
28
|
+
mary = create_person('Mary')
|
29
|
+
luke = create_person('Luke')
|
30
|
+
|
31
|
+
make_mutual_friends(johnathan, mark)
|
32
|
+
make_mutual_friends(mark, mary)
|
33
|
+
make_mutual_friends(mark, phill)
|
34
|
+
make_mutual_friends(phill, mary)
|
35
|
+
make_mutual_friends(phill, luke)
|
36
|
+
|
37
|
+
puts "Johnathan should become friends with #{suggestions_for(johnathan).map{|n| n["data"]["name"]}.join(', ')}"
|
38
|
+
|
39
|
+
# RESULT
|
40
|
+
# Johnathan should become friends with Mary, Phill
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'neography'
|
3
|
+
|
4
|
+
@neo = Neography::Rest.new
|
5
|
+
|
6
|
+
def suggestions_for(node)
|
7
|
+
node.incoming(:friends).order("breadth first").uniqueness("node global").filter("position.length() == 2;").depth(2)
|
8
|
+
end
|
9
|
+
|
10
|
+
johnathan = Neography::Node.create("name" =>'Johnathan')
|
11
|
+
mark = Neography::Node.create("name" =>'Mark')
|
12
|
+
phill = Neography::Node.create("name" =>'Phill')
|
13
|
+
mary = Neography::Node.create("name" =>'Mary')
|
14
|
+
luke = Neography::Node.create("name" =>'Luke')
|
15
|
+
|
16
|
+
johnathan.both(:friends) << mark
|
17
|
+
mark.both(:friends) << mary
|
18
|
+
mark.both(:friends) << phill
|
19
|
+
phill.both(:friends) << mary
|
20
|
+
phill.both(:friends) << luke
|
21
|
+
|
22
|
+
puts "Johnathan should become friends with #{suggestions_for(johnathan).map{|n| n.name }.join(', ')}"
|
23
|
+
|
24
|
+
# RESULT
|
25
|
+
# Johnathan should become friends with Mary, Phill
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'neography'
|
3
|
+
|
4
|
+
def create_great(name)
|
5
|
+
Neography::Node.create("name" => name)
|
6
|
+
end
|
7
|
+
|
8
|
+
game = create_great('The 1958 NFL Championship Game')
|
9
|
+
brando = create_great('Marlon Brando')
|
10
|
+
alex = create_great('Alexander the Great')
|
11
|
+
circus = create_great('The Ringling Bros. and Barnum and Bailey')
|
12
|
+
beatles = create_great('The Beatles')
|
13
|
+
ali = create_great('Muhammad Ali')
|
14
|
+
bread = create_great('Sliced Bread')
|
15
|
+
gatsby = create_great('The Great Gatsby')
|
16
|
+
|
17
|
+
greats = [game,brando,alex,circus,beatles,ali,bread,gatsby]
|
18
|
+
|
19
|
+
def as_great(great, other_greats)
|
20
|
+
other_greats.each do |og|
|
21
|
+
great.outgoing(:as_great) << og
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
greats.each do |g|
|
26
|
+
ogs = greats.select{|v| v != g }.sample(1 + rand(5))
|
27
|
+
as_great(g, ogs)
|
28
|
+
end
|
29
|
+
|
30
|
+
def the_greatest
|
31
|
+
neo = Neography::Rest.new
|
32
|
+
neo.execute_script("m = [:];
|
33
|
+
c = 0;
|
34
|
+
g.
|
35
|
+
V.
|
36
|
+
out.
|
37
|
+
groupCount(m).
|
38
|
+
loop(2){c++ < 1000}.iterate();
|
39
|
+
|
40
|
+
m.sort{a,b -> b.value <=> a.value}.keySet().name[0];")
|
41
|
+
end
|
42
|
+
|
43
|
+
puts "The greatest is #{the_greatest}"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'neography'
|
3
|
+
|
4
|
+
@neo = Neography::Rest.new
|
5
|
+
|
6
|
+
def create_person(name)
|
7
|
+
@neo.create_node("name" => name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def make_mutual_friends(node1, node2)
|
11
|
+
@neo.create_relationship("friends", node1, node2)
|
12
|
+
@neo.create_relationship("friends", node2, node1)
|
13
|
+
end
|
14
|
+
|
15
|
+
def degrees_of_separation(start_node, destination_node)
|
16
|
+
paths = @neo.get_paths(start_node, destination_node, {"type"=> "friends", "direction" => "in"}, depth=4, algorithm="allSimplePaths")
|
17
|
+
paths.each do |p|
|
18
|
+
p["names"] = p["nodes"].collect {|node| @neo.get_node_properties(node, "name")["name"] }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
johnathan = create_person('Johnathan')
|
24
|
+
mark = create_person('Mark')
|
25
|
+
phill = create_person('Phill')
|
26
|
+
mary = create_person('Mary')
|
27
|
+
|
28
|
+
make_mutual_friends(johnathan, mark)
|
29
|
+
make_mutual_friends(mark, phill)
|
30
|
+
make_mutual_friends(phill, mary)
|
31
|
+
make_mutual_friends(mark, mary)
|
32
|
+
|
33
|
+
degrees_of_separation(johnathan, mary).each do |path|
|
34
|
+
puts path["names"].join(' => friends => ')
|
35
|
+
end
|
36
|
+
|
37
|
+
# RESULT
|
38
|
+
# Johnathan => friends => Mark => friends => Phill => friends => Mary
|
39
|
+
# Johnathan => friends => Mark => friends => Mary
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'neography'
|
3
|
+
|
4
|
+
@neo = Neography::Rest.new
|
5
|
+
|
6
|
+
johnathan = Neography::Node.create("name" =>'Johnathan')
|
7
|
+
mark = Neography::Node.create("name" =>'Mark')
|
8
|
+
phill = Neography::Node.create("name" =>'Phill')
|
9
|
+
mary = Neography::Node.create("name" =>'Mary')
|
10
|
+
|
11
|
+
johnathan.both(:friends) << mark
|
12
|
+
mark.both(:friends) << phill
|
13
|
+
phill.both(:friends) << mary
|
14
|
+
mark.both(:friends) << mary
|
15
|
+
|
16
|
+
johnathan.all_simple_paths_to(mary).incoming(:friends).depth(4).nodes.each do |node|
|
17
|
+
puts node.map{|n| n.name }.join(' => friends => ')
|
18
|
+
end
|
19
|
+
|
20
|
+
# RESULT
|
21
|
+
# Johnathan => friends => Mark => friends => Phill => friends => Mary
|
22
|
+
# Johnathan => friends => Mark => friends => Mary
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'neography'
|
3
|
+
|
4
|
+
@neo = Neography::Rest.new
|
5
|
+
|
6
|
+
def create_node(level, type)
|
7
|
+
@neo.create_node("NODE_LEVEL" => level, "TYPE" => type)
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_other_node(type)
|
11
|
+
@neo.create_node("TYPE" => type)
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def get_nodes_by_level(level, node)
|
16
|
+
starting_id = node["self"].split('/').last
|
17
|
+
|
18
|
+
@neo.traverse(node,"nodes", {"order" => "breadth first",
|
19
|
+
"uniqueness" => "node global",
|
20
|
+
"relationships" => {"type"=> "linked", "direction" => "out"},
|
21
|
+
"prune evaluator" => {
|
22
|
+
"language" => "javascript",
|
23
|
+
"body" => "position.startNode().hasProperty('NODE_LEVEL')
|
24
|
+
&& position.startNode().getProperty('NODE_LEVEL')==5
|
25
|
+
&& position.startNode().getId()!=#{starting_id};"},
|
26
|
+
"return filter" => {
|
27
|
+
"language" => "javascript",
|
28
|
+
"body" => "position.endNode().hasProperty('NODE_LEVEL') && position.endNode().getProperty('NODE_LEVEL')==5;"}})
|
29
|
+
end
|
30
|
+
|
31
|
+
node1 = create_node(5, "N")
|
32
|
+
node2 = create_node(5, "N")
|
33
|
+
node3 = create_node(5, "N")
|
34
|
+
node4 = create_node(5, "N")
|
35
|
+
node5 = create_node(5, "N")
|
36
|
+
node6 = create_node(5, "N")
|
37
|
+
node7 = create_node(5, "N")
|
38
|
+
|
39
|
+
node8 = create_other_node("Y")
|
40
|
+
node9 = create_other_node("Y")
|
41
|
+
node10 = create_other_node("Y")
|
42
|
+
|
43
|
+
node11 = create_node(6, "N")
|
44
|
+
node12 = create_node(7, "N")
|
45
|
+
node13 = create_node(8, "N")
|
46
|
+
|
47
|
+
|
48
|
+
@neo.create_relationship("linked", node1, node2)
|
49
|
+
@neo.create_relationship("linked", node2, node3)
|
50
|
+
@neo.create_relationship("linked", node3, node4)
|
51
|
+
@neo.create_relationship("linked", node4, node5)
|
52
|
+
@neo.create_relationship("linked", node5, node6)
|
53
|
+
@neo.create_relationship("linked", node6, node7)
|
54
|
+
|
55
|
+
@neo.create_relationship("linked", node2, node8)
|
56
|
+
@neo.create_relationship("linked", node3, node9)
|
57
|
+
@neo.create_relationship("linked", node4, node10)
|
58
|
+
|
59
|
+
@neo.create_relationship("linked", node5, node11)
|
60
|
+
@neo.create_relationship("linked", node6, node12)
|
61
|
+
@neo.create_relationship("linked", node7, node13)
|
62
|
+
|
63
|
+
puts "The node levels returned are #{get_nodes_by_level(5, node1).map{|n| n["data"]["NODE_LEVEL"]}.join(', ')}"
|
64
|
+
|
65
|
+
# The node levels returned are 5, 5, 5, 5, 5, 5, 5
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'neography'
|
3
|
+
|
4
|
+
@neo = Neography::Rest.new
|
5
|
+
|
6
|
+
def create_node(name, mysql_id)
|
7
|
+
@neo.create_node("name" => name, "mysql_id" => mysql_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
def attended(student, school, degree, graduated)
|
11
|
+
@neo.create_relationship("attended", student, school, {"degree" => degree, "graduated" => graduated})
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def graduated_with_me(student)
|
16
|
+
student = student["self"].split('/').last
|
17
|
+
student_attended = @neo.get_node_relationships(student)[0]
|
18
|
+
graduated = student_attended["data"]["graduated"]
|
19
|
+
school = student_attended["end"].split('/').last
|
20
|
+
|
21
|
+
@neo.traverse(school,"nodes", {"order" => "breadth first",
|
22
|
+
"uniqueness" => "node global",
|
23
|
+
"relationships" => {"type"=> "attended", "direction" => "in"},
|
24
|
+
"return filter" => {
|
25
|
+
"language" => "javascript",
|
26
|
+
"body" => "position.length() == 1
|
27
|
+
&& position.endNode().getId() != #{student}
|
28
|
+
&& position.lastRelationship().getProperty(\"graduated\") == #{graduated};"}})
|
29
|
+
end
|
30
|
+
|
31
|
+
charlie = create_node("Charlie", 1)
|
32
|
+
max = create_node("Max", 2)
|
33
|
+
peter = create_node("Peter", 3)
|
34
|
+
carol = create_node("Carol", 3)
|
35
|
+
tom = create_node("Tom", 4)
|
36
|
+
jerry = create_node("Jerry", 5)
|
37
|
+
larry = create_node("Larry", 6)
|
38
|
+
|
39
|
+
yale = create_node("Yale", 7)
|
40
|
+
harvard = create_node("Harvard", 8)
|
41
|
+
rutgers = create_node("Rutgers", 9)
|
42
|
+
|
43
|
+
attended(charlie,yale,"engineering", 2010)
|
44
|
+
attended(max,yale,"mathematics", 2005)
|
45
|
+
attended(peter,yale,"biology", 2010)
|
46
|
+
attended(carol,yale,"engineering", 2010)
|
47
|
+
attended(tom,harvard,"biology", 2008)
|
48
|
+
attended(jerry,rutgers,"physics", 2007)
|
49
|
+
attended(larry,rutgers,"mathematics", 2010)
|
50
|
+
|
51
|
+
|
52
|
+
puts "Charlie graduated with #{graduated_with_me(charlie).map{|n| n["data"]["name"]}.join(', ')}"
|
53
|
+
|
54
|
+
# The node levels returned are Peter, Carol
|
data/lib/neography.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
def find_and_require_user_defined_code
|
2
|
+
extensions_path = ENV['neography_extensions'] || "~/.neography"
|
3
|
+
extensions_path = File.expand_path(extensions_path)
|
4
|
+
if File.exists?(extensions_path)
|
5
|
+
Dir.open extensions_path do |dir|
|
6
|
+
dir.entries.each do |file|
|
7
|
+
if file.split('.').size > 1 && file.split('.').last == 'rb'
|
8
|
+
extension = File.join(File.expand_path(extensions_path), file)
|
9
|
+
require(extension) && puts("Loaded Extension: #{extension}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
DIRECTIONS = ["incoming", "in", "outgoing", "out", "all", "both"]
|
17
|
+
|
18
|
+
require 'cgi'
|
19
|
+
require 'httparty'
|
20
|
+
require 'json'
|
21
|
+
require 'logger'
|
22
|
+
require 'ostruct'
|
23
|
+
require 'os'
|
24
|
+
require 'zip/zipfilesystem'
|
25
|
+
|
26
|
+
require 'neography/config'
|
27
|
+
require 'neography/rest'
|
28
|
+
require 'neography/neography'
|
29
|
+
|
30
|
+
require 'neography/property_container'
|
31
|
+
require 'neography/property'
|
32
|
+
require 'neography/node_relationship'
|
33
|
+
require 'neography/node_path'
|
34
|
+
require 'neography/relationship_traverser'
|
35
|
+
require 'neography/node_traverser'
|
36
|
+
require 'neography/path_traverser'
|
37
|
+
require 'neography/equal'
|
38
|
+
require 'neography/index'
|
39
|
+
|
40
|
+
require 'neography/node'
|
41
|
+
require 'neography/relationship'
|
42
|
+
|
43
|
+
require 'neography/railtie' if defined? Rails::Railtie
|
44
|
+
|
45
|
+
find_and_require_user_defined_code
|
46
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Neography
|
2
|
+
class Config
|
3
|
+
class << self; attr_accessor :protocol, :server, :port, :directory, :log_file, :log_enabled, :logger, :max_threads, :authentication, :username, :password end
|
4
|
+
|
5
|
+
@protocol = 'http://'
|
6
|
+
@server = 'localhost'
|
7
|
+
@port = 7474
|
8
|
+
@directory = ''
|
9
|
+
@log_file = 'neography.log'
|
10
|
+
@log_enabled = false
|
11
|
+
@logger = Logger.new(@log_file) if @log_enabled
|
12
|
+
@max_threads = 20
|
13
|
+
@authentication = {}
|
14
|
+
@username = nil
|
15
|
+
@password = nil
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Neography
|
2
|
+
|
3
|
+
# == This mixin is used for both nodes and relationships to decide if two entities are equal or not.
|
4
|
+
#
|
5
|
+
module Equal
|
6
|
+
def equal?(o)
|
7
|
+
eql?(o)
|
8
|
+
end
|
9
|
+
|
10
|
+
def eql?(o)
|
11
|
+
return false unless o.respond_to?(:neo_id)
|
12
|
+
o.neo_id == neo_id
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(o)
|
16
|
+
eql?(o)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Neography
|
2
|
+
class Node < PropertyContainer
|
3
|
+
extend Neography::Index
|
4
|
+
include Neography::NodeRelationship
|
5
|
+
include Neography::NodePath
|
6
|
+
include Neography::Equal
|
7
|
+
include Neography::Property
|
8
|
+
|
9
|
+
attr_accessor :neo_server
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def create(*args)
|
13
|
+
# the arguments can be an hash of properties to set or a rest instance
|
14
|
+
props = (args[0].respond_to?(:each_pair) && args[0]) || args[1]
|
15
|
+
db = (args[0].is_a?(Neography::Rest) && args[0]) || args[1] || Neography::Rest.new
|
16
|
+
node = self.new(db.create_node(props))
|
17
|
+
node.neo_server = db
|
18
|
+
node
|
19
|
+
end
|
20
|
+
|
21
|
+
def load(*args)
|
22
|
+
# the first argument can be an hash of properties to set
|
23
|
+
node = !args[0].is_a?(Neography::Rest) && args[0] || args[1]
|
24
|
+
|
25
|
+
# a db instance can be given, it is the first argument or the second
|
26
|
+
db = (args[0].is_a?(Neography::Rest) && args[0]) || args[1] || Neography::Rest.new
|
27
|
+
node = db.get_node(node)
|
28
|
+
node = self.new(node) unless node.nil?
|
29
|
+
node.neo_server = db unless node.nil?
|
30
|
+
node
|
31
|
+
end
|
32
|
+
|
33
|
+
#alias_method :new, :create
|
34
|
+
end
|
35
|
+
|
36
|
+
def del
|
37
|
+
self.neo_server.delete_node!(self.neo_id)
|
38
|
+
end
|
39
|
+
|
40
|
+
def exist?
|
41
|
+
!self.neo_server.get_node(self.neo_id).nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|