neography 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- neography (0.0.3)
4
+ neography (0.0.4)
5
5
  httparty (~> 0.6.1)
6
6
  json
7
7
 
@@ -13,6 +13,7 @@ GEM
13
13
  fakeweb (1.3.0)
14
14
  httparty (0.6.1)
15
15
  crack (= 0.1.8)
16
+ json (1.4.6)
16
17
  json (1.4.6-java)
17
18
  net-http-spy (0.2.1)
18
19
  rspec (2.0.1)
@@ -28,6 +29,7 @@ GEM
28
29
 
29
30
  PLATFORMS
30
31
  java
32
+ ruby
31
33
 
32
34
  DEPENDENCIES
33
35
  fakeweb (~> 1.3.0)
data/README.rdoc CHANGED
@@ -35,12 +35,12 @@ Just add gem 'neography' to your Gemfile and run bundle install
35
35
 
36
36
  A thin ruby wrapper Neography::Rest which tries to mirror the Neo4j Rest API and returns JSON or Nil:
37
37
 
38
- # protocol, server, port, log_file, log_enabled
39
- @neo = Neography::Rest.new ('http://', '192.168.10.1', 7479, 'log/neography.log', true)
38
+ # protocol, server, port, log_file, log_enabled, max_threads
39
+ @neo = Neography::Rest.new ('http://', '192.168.10.1', 7479, 'log/neography.log', true, 50)
40
40
 
41
41
  Default Parameters are:
42
42
 
43
- @neo = Neography::Rest.new ('http://', 'localhost', 7474, '/neography.log', false)
43
+ @neo = Neography::Rest.new ('http://', 'localhost', 7474, '/neography.log', false, 20)
44
44
 
45
45
  To Use:
46
46
 
@@ -104,6 +104,72 @@ To Use:
104
104
 
105
105
  Please see the specs for more examples.
106
106
 
107
+ Experimental:
108
+
109
+ nodes = @neo.create_nodes(5) # Create 5 empty nodes
110
+ nodes = @neo.create_nodes_threaded(5) # Create 5 empty nodes using threads
111
+ nodes = @neo.create_node_nodes([{"age" => 31, "name" => "Max"},
112
+ {"age" => 24, "name" => "Alex"}) # Create two nodes with properties
113
+ nodes = @neo.create_node_nodes_threaded([{"age" => 31, "name" => "Max"},
114
+ {"age" => 24, "name" => "Alex"}) # Create two nodes with properties threaded
115
+ nodes = @neo.get_nodes([17,86,397,33]) # Get four nodes by their id
116
+
117
+ one_set_nodes = @neo.create_nodes(3)
118
+ another_node = @neo.create_node("age" => 31, "name" => "Max")
119
+ nodes = @neo.get_nodes([one_set_nodes, another_node]) # Get four nodes
120
+
121
+ === Phase 2 (work in progress):
122
+
123
+ Trying to mimic the Neo4j.rb API.
124
+
125
+ Now we are returning full objects. The properties of the node or relationship can be accessed directly (node.name).
126
+ The Neo4j ID is available by using node.neo_id .
127
+
128
+ @neo2 = Neography::Rest.new ('http://', '192.168.10.1')
129
+
130
+ Neography::Node.create # Create an empty node
131
+ Neography::Node.create("age" => 31, "name" => "Max") # Create a node with some properties
132
+ Neography::Node.create(@neo2, {"age" => 31, "name" => "Max"}) # Create a node on the server defined in @neo2
133
+ Neography::Node.create({"age" => 31, "name" => "Max"}, @neo2) # Same as above, but different order
134
+
135
+ Neography::Node.load(5) # Get a node and its properties by id
136
+ Neography::Node.load(existing_node) # Get a node and its properties by Node
137
+ Neography::Node.load("http://localhost:7474/db/data/node/2") # Get a node and its properties by String
138
+
139
+ Neography::Node.load(@neo2, 5) # Get a node on the server defined in @neo2
140
+ Neography::Node.load(5, @neo2) # Same as above, but different order
141
+
142
+ n1 = Node.create
143
+ n1.del # Deletes the node
144
+ n1.exist? # returns true/false if node exists in Neo4j
145
+
146
+ n1 = Node.create("age" => 31, "name" => "Max")
147
+ n1[:age] #returns 31 # Get a node property using [:key]
148
+ n1.name #returns "Max" # Get a node property as a method
149
+ n1[:age] = 24 # Set a node property using [:key] =
150
+ n1.name = "Alex" # Set a node property as a method
151
+ n1[:hair] = "black" # Add a node property using [:key] =
152
+ n1.weight = 190 # Add a node property as a method
153
+ n1[:name] = nil # Delete a node property using [:key] = nil
154
+ n1.name = nil # Delete a node property by setting it to nil
155
+
156
+ n2 = Neography::Node.create
157
+ new_rel = Neography::Relationship.create(:family, n1, n2) # Create a relationship from my_node to node2
158
+ new_rel.start_node # Get the start/from node of a relationship
159
+ new_rel.end_node # Get the end/to node of a relationship
160
+ existing_rel = Neography::Relationship.load(12) # Get an existing relationship by id
161
+ existing_rel.del # Delete a relationship
162
+
163
+ Neography::Relationship.create(:friends, n1, n2)
164
+ n1.rel?(:friends) # Has a friends relationship
165
+ n1.rel?(:outgoing, :friends) # Has outgoing friends relationship
166
+ n1.rel?(:friends, :outgoing) # same, just the other way
167
+ n1.rel?(:outgoing) # Has any outgoing relationships
168
+ n1.rel?(:both) # Has any relationships
169
+ n1.rel?(:all) # same as above
170
+ n1.rel? # same as above
171
+
172
+
107
173
  See Neo4j API for:
108
174
  * {Order}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/graphdb/Traverser.Order.html]
109
175
  * {Uniqueness}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/kernel/Uniqueness.html]
@@ -0,0 +1,14 @@
1
+ module Neography
2
+ class Config
3
+ class << self; attr_accessor :protocol, :server, :port, :log_file, :log_enabled, :logger, :max_threads end
4
+
5
+ @protocol = 'http://'
6
+ @server = 'localhost'
7
+ @port = 7474
8
+ @log_file = 'neography.log'
9
+ @log_enabled = false
10
+ @logger = Logger.new(@log_file) if @log_enabled
11
+ @max_threads = 20
12
+
13
+ end
14
+ 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,10 @@
1
+ module Neography
2
+
3
+ class << self
4
+
5
+ def ref_node(this_db = Neography::Rest.new)
6
+ this_db.get_root
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,43 @@
1
+ module Neography
2
+ class Node < PropertyContainer
3
+ include Neography::NodeRelationship
4
+ include Neography::Equal
5
+ include Neography::Property
6
+
7
+ attr_accessor :neo_server
8
+
9
+ class << self
10
+ def create(*args)
11
+ # the arguments can be an hash of properties to set or a rest instance
12
+ props = (args[0].respond_to?(:each_pair) && args[0]) || args[1]
13
+ db = (args[0].is_a?(Neography::Rest) && args[0]) || args[1] || Neography::Rest.new
14
+ node = Neography::Node.new(db.create_node(props))
15
+ node.neo_server = db
16
+ node
17
+ end
18
+
19
+ def load(*args)
20
+ # the first argument can be an hash of properties to set
21
+ node = !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
+ node = db.get_node(node)
26
+ node = Neography::Node.new(node) unless node.nil?
27
+ node.neo_server = db unless node.nil?
28
+ node
29
+ end
30
+
31
+ #alias_method :new, :create
32
+ end
33
+
34
+ def del
35
+ self.neo_server.delete_node!(self.neo_id)
36
+ end
37
+
38
+ def exist?
39
+ !self.neo_server.get_node(self.neo_id).nil?
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ module Neography
2
+ module NodeRelationship
3
+
4
+ def outgoing(types=nil)
5
+ if types
6
+ NodeTraverser.new(self).outgoing(types)
7
+ else
8
+ NodeTraverser.new(self).outgoing
9
+ end
10
+ end
11
+
12
+ def incoming(types=nil)
13
+ if types
14
+ NodeTraverser.new(self).incoming(types)
15
+ else
16
+ NodeTraverser.new(self).incoming
17
+ end
18
+ end
19
+
20
+ def both(types=nil)
21
+ if types
22
+ NodeTraverser.new(self).both(types)
23
+ else
24
+ NodeTraverser.new(self) # default is both
25
+ end
26
+ end
27
+
28
+ def rels(*types)
29
+ Neography::RelationshipTraverser.new(self, types, :both)
30
+ end
31
+
32
+ def rel(dir, type)
33
+ Neography::RelationshipTraverser.new(self, type, dir).first
34
+ end
35
+
36
+ def rel?(dir=nil, type=nil)
37
+ if DIRECTIONS.include?(dir.to_s)
38
+ !self.neo_server.get_node_relationships(self, dir, type).nil?
39
+ else
40
+ !self.neo_server.get_node_relationships(self, type, dir).nil?
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ module Neography
2
+ class NodeTraverser
3
+ include Enumerable
4
+
5
+ attr_accessor :order, :uniqueness, :depth, :prune, :filter
6
+
7
+ def initialize(from, types = nil, dir=nil)
8
+ @from = from
9
+ @depth = 1
10
+ @order = "depth first"
11
+ @uniqueness = "none"
12
+ if types.nil? || dir.nil?
13
+ # @td = org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl.new.breadth_first()
14
+ else
15
+ # @types = type_to_java(type)
16
+ # @dir = dir_to_java(dir)
17
+ # @td = org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl.new.breadth_first().relationships(@type, @dir)
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,55 @@
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
+ @table[key] = nil
16
+ else
17
+ neo_server.remove_relationship_properties(self.neo_id, [key])
18
+ @table[key] = nil
19
+ end
20
+ else
21
+ if self.is_a? Neography::Node
22
+ neo_server.set_node_properties(self.neo_id, {k => value})
23
+ else
24
+ neo_server.set_relationship_properties(self.neo_id, {k => value})
25
+ end
26
+
27
+ new_ostruct_member(k) unless self.respond_to?(key)
28
+
29
+ end
30
+ end
31
+
32
+
33
+ def new_ostruct_member(name)
34
+ name = name.to_sym
35
+ unless self.respond_to?(name)
36
+ meta = class << self; self; end
37
+ meta.send(:define_method, name) { @table[name] }
38
+ meta.send(:define_method, "#{name}=") do |x|
39
+ @table[name] = x
40
+ self[name.to_sym] = x
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ def self.method_missing(method_sym, *arguments, &block)
47
+ if (method_sym.to_s =~ /$=/) != nil
48
+ new_ostruct_member(method_sym.to_s.chomp("="))
49
+ else
50
+ super
51
+ end
52
+ end
53
+
54
+ end
55
+ 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,54 @@
1
+ module Neography
2
+ class Relationship < PropertyContainer
3
+ include Neography::Equal
4
+ include Neography::Property
5
+
6
+ attr_accessor :start_node, :end_node, :rel_type
7
+
8
+ class << self
9
+
10
+ def create(type, from_node, to_node, props=nil)
11
+ rel = Neography::Relationship.new(from_node.neo_server.create_relationship(type, from_node, to_node, props))
12
+ rel.start_node = from_node
13
+ rel.end_node = to_node
14
+ rel.rel_type = type
15
+ rel
16
+ end
17
+
18
+ def load(*args)
19
+ # the first argument can be an hash of properties to set
20
+ rel = !args[0].is_a?(Neography::Rest) && args[0] || args[1]
21
+
22
+ # a db instance can be given, it is the first argument or the second
23
+ db = (args[0].is_a?(Neography::Rest) && args[0]) || args[1] || Neography::Rest.new
24
+ rel = db.get_relationship(rel)
25
+ unless rel.nil?
26
+ rel = Neography::Relationship.new(rel)
27
+ rel.start_node = Neography::Node.load(rel.start_node)
28
+ rel.end_node = Neography::Node.load(rel.end_node)
29
+ end
30
+ rel
31
+ end
32
+ end
33
+
34
+ def initialize(hash=nil, neo_server=nil)
35
+ super(hash)
36
+ @start_node = hash["start"].split('/').last
37
+ @end_node = hash["end"].split('/').last
38
+ @rel_type = hash["type"]
39
+ end
40
+
41
+ def del
42
+ self.start_node.neo_server.delete_relationship(self.neo_id)
43
+ end
44
+
45
+ def other_node(node)
46
+ if node = @start_node
47
+ @end_node
48
+ else
49
+ @start_node
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ module Neography
2
+ class RelationshipTraverser
3
+ include Enumerable
4
+
5
+ def initialize(node, types, direction)
6
+ @node = node
7
+ @types = [types]
8
+ @direction = direction
9
+ end
10
+
11
+ def to_s
12
+ if @types.size == 1 && !@types.empty?
13
+ "#{self.class} [type: #{@type} dir:#{@direction}]"
14
+ elsif !@types.empty?
15
+ "#{self.class} [types: #{@types.join(',')} dir:#{@direction}]"
16
+ else
17
+ "#{self.class} [types: ANY dir:#{@direction}]"
18
+ end
19
+ end
20
+
21
+ def each
22
+ iterator.each { |i| yield Neography::Relationship.new(i, @node.neo_server) }
23
+ end
24
+
25
+ def empty?
26
+ first == nil
27
+ end
28
+
29
+ def iterator
30
+ @node.neo_server.get_node_relationships(@node, @direction, @types)
31
+ end
32
+
33
+ def del
34
+ each { |rel| @node.neo_server.delete_relationship(rel) }
35
+ end
36
+
37
+ def size
38
+ [*self].size
39
+ end
40
+
41
+ def both
42
+ @direction = :both
43
+ self
44
+ end
45
+
46
+ def incoming
47
+ raise "Not allowed calling incoming when finding several relationships types" if @types
48
+ @direction = :incoming
49
+ self
50
+ end
51
+
52
+ def outgoing
53
+ raise "Not allowed calling outgoing when finding several relationships types" if @types
54
+ @direction = :outgoing
55
+ self
56
+ end
57
+
58
+ end
59
+ end
@@ -1,15 +1,21 @@
1
1
  module Neography
2
2
  class Rest
3
3
  include HTTParty
4
- attr_accessor :protocol, :server, :port, :log_file, :log_enabled, :logger
5
-
6
- def initialize(protocol='http://', server='localhost', port=7474, log_file='neography.log', log_enabled=false)
4
+ attr_accessor :protocol, :server, :port, :log_file, :log_enabled, :logger, :max_threads
5
+
6
+ def initialize(protocol=Neography::Config.protocol,
7
+ server=Neography::Config.server,
8
+ port=Neography::Config.port,
9
+ log_file=Neography::Config.log_file,
10
+ log_enabled=Neography::Config.log_enabled,
11
+ max_threads=Neography::Config.max_threads)
7
12
  @protocol = protocol
8
13
  @server = server
9
14
  @port = port
10
15
  @log_file = log_file
11
16
  @log_enabled = log_enabled
12
17
  @logger = Logger.new(@log_file) if @log_enabled
18
+ @max_threads = max_threads
13
19
  end
14
20
 
15
21
  def configure(protocol, server, port)
@@ -35,10 +41,67 @@ module Neography
35
41
  end
36
42
  end
37
43
 
44
+ def create_nodes(nodes)
45
+ nodes = Array.new(nodes) if nodes.kind_of? Fixnum
46
+ created_nodes = Array.new
47
+ nodes.each do |node|
48
+ created_nodes << create_node(node)
49
+ end
50
+ created_nodes
51
+ end
52
+
53
+ def create_nodes_threaded(nodes)
54
+ nodes = Array.new(nodes) if nodes.kind_of? Fixnum
55
+
56
+ node_queue = Queue.new
57
+ thread_pool = []
58
+ responses = Queue.new
59
+
60
+ nodes.each do |node|
61
+ node_queue.push node
62
+ end
63
+
64
+ [nodes.size, @max_threads].min.times do
65
+ thread_pool << Thread.new do
66
+ until node_queue.empty? do
67
+ node = node_queue.pop
68
+ if node.respond_to?(:each_pair)
69
+ responses.push( post("/node", { :body => node.to_json, :headers => {'Content-Type' => 'application/json'} } ) )
70
+ else
71
+ responses.push( post("/node") )
72
+ end
73
+ end
74
+ self.join
75
+ end
76
+ end
77
+
78
+ created_nodes = Array.new
79
+
80
+ while created_nodes.size < nodes.size
81
+ created_nodes << responses.pop
82
+ end
83
+ created_nodes
84
+ end
85
+
86
+ # This is not yet implemented in the REST API
87
+ #
88
+ # def get_all_node
89
+ # puts "get all nodes"
90
+ # get("/nodes/")
91
+ # end
92
+
38
93
  def get_node(id)
39
94
  get("/node/#{get_id(id)}")
40
95
  end
41
96
 
97
+ def get_nodes(*nodes)
98
+ gotten_nodes = Array.new
99
+ Array(nodes).flatten.each do |node|
100
+ gotten_nodes << get_node(node)
101
+ end
102
+ gotten_nodes
103
+ end
104
+
42
105
  def reset_node_properties(id, properties)
43
106
  options = { :body => properties.to_json, :headers => {'Content-Type' => 'application/json'} }
44
107
  put("/node/#{get_id(id)}/properties", options)
@@ -49,7 +112,7 @@ module Neography
49
112
  get("/node/#{get_id(id)}/properties")
50
113
  else
51
114
  node_properties = Hash.new
52
- properties.to_a.each do |property|
115
+ Array(properties).each do |property|
53
116
  value = get("/node/#{get_id(id)}/properties/#{property}")
54
117
  node_properties[property] = value unless value.nil?
55
118
  end
@@ -62,7 +125,7 @@ module Neography
62
125
  if properties.nil?
63
126
  delete("/node/#{get_id(id)}/properties")
64
127
  else
65
- properties.to_a.each do |property|
128
+ Array(properties).each do |property|
66
129
  delete("/node/#{get_id(id)}/properties/#{property}")
67
130
  end
68
131
  end
@@ -98,7 +161,7 @@ module Neography
98
161
  get("/relationship/#{get_id(id)}/properties")
99
162
  else
100
163
  relationship_properties = Hash.new
101
- properties.to_a.each do |property|
164
+ Array(properties).each do |property|
102
165
  value = get("/relationship/#{get_id(id)}/properties/#{property}")
103
166
  relationship_properties[property] = value unless value.nil?
104
167
  end
@@ -111,7 +174,7 @@ module Neography
111
174
  if properties.nil?
112
175
  delete("/relationship/#{get_id(id)}/properties")
113
176
  else
114
- properties.to_a.each do |property|
177
+ Array(properties).each do |property|
115
178
  delete("/relationship/#{get_id(id)}/properties/#{property}")
116
179
  end
117
180
  end
@@ -134,7 +197,7 @@ module Neography
134
197
  if types.nil?
135
198
  node_relationships = get("/node/#{get_id(id)}/relationships/#{dir}") || Array.new
136
199
  else
137
- node_relationships = get("/node/#{get_id(id)}/relationships/#{dir}/#{types.to_a.join('&')}") || Array.new
200
+ node_relationships = get("/node/#{get_id(id)}/relationships/#{dir}/#{Array(types).join('&')}") || Array.new
138
201
  end
139
202
  return nil if node_relationships.empty?
140
203
  node_relationships
@@ -235,6 +298,8 @@ module Neography
235
298
  id["self"].split('/').last
236
299
  when String
237
300
  id.split('/').last
301
+ when Neography::Node, Neography::Relationship
302
+ id.neo_id
238
303
  else
239
304
  id
240
305
  end
@@ -1,3 +1,3 @@
1
1
  module Neography
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/neography.rb CHANGED
@@ -15,12 +15,28 @@ def find_and_require_user_defined_code
15
15
  end
16
16
  end
17
17
 
18
+ DIRECTIONS = ["incoming", "in", "outgoing", "out", "all", "both"]
19
+
18
20
 
19
21
  require 'httparty'
20
22
  require 'json'
21
23
  require 'logger'
24
+ require 'ostruct'
22
25
 
26
+ require 'neography/config'
23
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/relationship_traverser'
34
+ require 'neography/node_traverser'
35
+ require 'neography/equal'
36
+
37
+
38
+ require 'neography/node'
39
+ require 'neography/relationship'
24
40
 
25
41
  find_and_require_user_defined_code
26
42
 
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Neography do
4
+ describe "ref_node" do
5
+ it "can get the reference node" do
6
+ root_node = Neography.ref_node
7
+ root_node.should have_key("reference_node")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,198 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Neography::Node do
4
+
5
+ describe "create and new" do
6
+ it "can create an empty node" do
7
+ new_node = Neography::Node.create
8
+ new_node.should_not be_nil
9
+ end
10
+
11
+ it "can create a node with one property" do
12
+ new_node = Neography::Node.create("name" => "Max")
13
+ new_node.name.should == "Max"
14
+ end
15
+
16
+ it "can create a node with more than one property" do
17
+ new_node = Neography::Node.create("age" => 31, "name" => "Max")
18
+ new_node.name.should == "Max"
19
+ new_node.age.should == 31
20
+ end
21
+
22
+ it "can create a node with more than one property not on the default rest server" do
23
+ @neo = Neography::Rest.new
24
+ new_node = Neography::Node.create({"age" => 31, "name" => "Max"}, @neo)
25
+ new_node.name.should == "Max"
26
+ new_node.age.should == 31
27
+ end
28
+
29
+ it "can create a node with more than one property not on the default rest server the other way" do
30
+ @neo = Neography::Rest.new
31
+ new_node = Neography::Node.create(@neo, {"age" => 31, "name" => "Max"})
32
+ new_node.name.should == "Max"
33
+ new_node.age.should == 31
34
+ end
35
+ end
36
+
37
+
38
+ describe "load" do
39
+ it "can get a node that exists" do
40
+ new_node = Neography::Node.create
41
+ existing_node = Neography::Node.load(new_node)
42
+ existing_node.should_not be_nil
43
+ existing_node.neo_id.should_not be_nil
44
+ existing_node.neo_id.should == new_node.neo_id
45
+ end
46
+
47
+ it "returns nil if it tries to load a node that does not exist" do
48
+ new_node = Neography::Node.create
49
+ fake_node = new_node.neo_id.to_i + 1000
50
+ existing_node = Neography::Node.load(fake_node)
51
+ existing_node.should be_nil
52
+ end
53
+
54
+ it "can load a node that exists not on the default rest server" do
55
+ @neo = Neography::Rest.new
56
+ new_node = Neography::Node.create(@neo)
57
+ existing_node = Neography::Node.load(new_node, @neo)
58
+ existing_node.should_not be_nil
59
+ existing_node.neo_id.should_not be_nil
60
+ existing_node.neo_id.should == new_node.neo_id
61
+ end
62
+
63
+ it "can load a node that exists not on the default rest server the other way" do
64
+ @neo = Neography::Rest.new
65
+ new_node = Neography::Node.create(@neo)
66
+ existing_node = Neography::Node.load(@neo, new_node)
67
+ existing_node.should_not be_nil
68
+ existing_node.neo_id.should_not be_nil
69
+ existing_node.neo_id.should == new_node.neo_id
70
+ end
71
+ end
72
+
73
+ describe "del" do
74
+ it "can delete itself" do
75
+ new_node = Neography::Node.create
76
+ node_id = new_node.neo_id
77
+ new_node.del
78
+ deleted_node = Neography::Node.load(node_id)
79
+ deleted_node.should be_nil
80
+ end
81
+ end
82
+
83
+ describe "exists?" do
84
+ it "can tell if it exists" do
85
+ new_node = Neography::Node.create
86
+ new_node.exist?.should be_true
87
+ end
88
+
89
+ it "can tell if does not exists" do
90
+ new_node = Neography::Node.create
91
+ new_node.del
92
+ new_node.exist?.should be_false
93
+ end
94
+ end
95
+
96
+ describe "equality" do
97
+ it "can tell two nodes are the same with equal?" do
98
+ new_node = Neography::Node.create
99
+ another_node = Neography::Node.load(new_node)
100
+ new_node.equal?(another_node).should be_true
101
+ end
102
+
103
+ it "can tell two nodes are the same with eql?" do
104
+ new_node = Neography::Node.create
105
+ another_node = Neography::Node.load(new_node)
106
+ new_node.eql?(another_node).should be_true
107
+ end
108
+
109
+ it "can tell two nodes are the same with ==" do
110
+ new_node = Neography::Node.create
111
+ another_node = Neography::Node.load(new_node)
112
+ (new_node == another_node).should be_true
113
+ end
114
+ end
115
+
116
+ describe "set properties" do
117
+ it "can change a node's properties that already exist using []=" do
118
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
119
+
120
+ new_node[:weight] = 200
121
+ new_node[:eyes] = "brown"
122
+
123
+ existing_node = Neography::Node.load(new_node)
124
+ existing_node.weight.should == 200
125
+ existing_node.eyes.should == "brown"
126
+ end
127
+
128
+ it "can change a node's properties that already exist" do
129
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
130
+
131
+ new_node.weight = 200
132
+ new_node.eyes = "brown"
133
+
134
+ existing_node = Neography::Node.load(new_node)
135
+ existing_node.weight.should == 200
136
+ existing_node.eyes.should == "brown"
137
+ end
138
+
139
+ it "can change a node's properties that does not already exist" do
140
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
141
+
142
+ new_node.weight = 200
143
+ new_node.eyes = "brown"
144
+ new_node[:hair] = "black"
145
+
146
+ existing_node = Neography::Node.load(new_node)
147
+ existing_node.weight.should == 200
148
+ existing_node.eyes.should == "brown"
149
+ existing_node.hair.should == "black"
150
+ end
151
+ end
152
+
153
+ describe "get node properties" do
154
+ it "can get node properties using []" do
155
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
156
+ new_node[:weight].should == 150
157
+ new_node[:eyes].should == "green"
158
+ end
159
+
160
+ it "can get node properties" do
161
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
162
+ new_node.weight.should == 150
163
+ new_node.eyes.should == "green"
164
+ end
165
+ end
166
+
167
+ describe "delete node properties" do
168
+ it "can delete node properties using []" do
169
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
170
+
171
+ new_node[:weight] = nil
172
+ new_node[:eyes] = nil
173
+
174
+ new_node[:weight].should be_nil
175
+ new_node[:eyes].should be_nil
176
+
177
+ existing_node = Neography::Node.load(new_node)
178
+ existing_node.weight.should be_nil
179
+ existing_node.eyes.should be_nil
180
+ end
181
+
182
+ it "can delete node properties" do
183
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
184
+
185
+ new_node.weight = nil
186
+ new_node.eyes = nil
187
+
188
+ new_node.weight.should be_nil
189
+ new_node.eyes.should be_nil
190
+
191
+ existing_node = Neography::Node.load(new_node)
192
+ existing_node.weight.should be_nil
193
+ existing_node.eyes.should be_nil
194
+ end
195
+ end
196
+
197
+
198
+ end
@@ -0,0 +1,71 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Neography::Relationship do
4
+ describe "create relationship" do
5
+ it "#new(:family, p1, p2) creates a new relationship between to nodes of given type" do
6
+ p1 = Neography::Node.create
7
+ p2 = Neography::Node.create
8
+
9
+ new_rel = Neography::Relationship.create(:family, p1, p2)
10
+ puts new_rel.inspect
11
+ new_rel.start_node.should == p1
12
+ new_rel.end_node.should == p2
13
+
14
+
15
+ # p1.outgoing(:family).should include(p2)
16
+ # p2.incoming(:family).should include(p1)
17
+ end
18
+
19
+ it "#new(:family, p1, p2, :since => '1998', :colour => 'blue') creates relationship and sets its properties" do
20
+ p1 = Neography::Node.create
21
+ p2 = Neography::Node.create
22
+
23
+ rel = Neography::Relationship.create(:family, p1, p2, :since => 1998, :colour => 'blue')
24
+ rel[:since].should == 1998
25
+ rel[:colour].should == 'blue'
26
+ rel.since.should == 1998
27
+ rel.colourshould == 'blue'
28
+ end
29
+
30
+ it "#outgoing(:friends).create(other) creates a new relationship between self and other node" do
31
+ p1 = Neography::Node.create
32
+ p2 = Neography::Node.create
33
+
34
+ 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
+
40
+ describe "rel?" do
41
+ it "#rel? returns true if there are any relationships" do
42
+ n1 = Neography::Node.create
43
+ n2 = Neography::Node.create
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
58
+ end
59
+ end
60
+
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
+ end
@@ -0,0 +1,106 @@
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 "can create many nodes threaded" do
9
+ it "can create empty nodes threaded" do
10
+ new_nodes = @neo.create_nodes_threaded(2)
11
+ new_nodes.should_not be_nil
12
+ new_nodes.size.should == 2
13
+ end
14
+
15
+ it "is faster than non-threaded?" do
16
+ Benchmark.bm do |x|
17
+ x.report("create 500 nodes ") { @not_threaded = @neo.create_nodes(500) }
18
+ x.report("create 500 nodes threaded") { @threaded = @neo.create_nodes_threaded(500) }
19
+ x.report("create 1000 nodes threaded") { @threaded2c = @neo.create_nodes_threaded(1000) }
20
+ end
21
+
22
+ @not_threaded[99].should_not be_nil
23
+ @threaded[99].should_not be_nil
24
+ @threaded2c[199].should_not be_nil
25
+ end
26
+
27
+ end
28
+
29
+ describe "can create many nodes" do
30
+ it "can create empty nodes" do
31
+ new_nodes = @neo.create_nodes(2)
32
+ new_nodes.should_not be_nil
33
+ new_nodes.size.should == 2
34
+ end
35
+
36
+ it "can create nodes with one property" do
37
+ new_nodes = @neo.create_nodes([{"name" => "Max"}, {"name" => "Alex"}])
38
+ new_nodes[0]["data"]["name"].should == "Max"
39
+ new_nodes[1]["data"]["name"].should == "Alex"
40
+ end
41
+
42
+ it "can create nodes with one property that are different" do
43
+ new_nodes = @neo.create_nodes([{"name" => "Max"}, {"age" => 24}])
44
+ new_nodes[0]["data"]["name"].should == "Max"
45
+ new_nodes[1]["data"]["age"].should == 24
46
+ end
47
+
48
+ it "can create nodes with more than one property" do
49
+ new_nodes = @neo.create_nodes([{"age" => 31, "name" => "Max"}, {"age" => 24, "name" => "Alex"}])
50
+ new_nodes[0]["data"]["name"].should == "Max"
51
+ new_nodes[0]["data"]["age"].should == 31
52
+ new_nodes[1]["data"]["name"].should == "Alex"
53
+ new_nodes[1]["data"]["age"].should == 24
54
+ end
55
+
56
+ it "can create nodes with more than one property that are different" do
57
+ new_nodes = @neo.create_nodes([{"age" => 31, "name" => "Max"}, {"height" => "5-11", "weight" => 215}])
58
+ new_nodes[0]["data"]["name"].should == "Max"
59
+ new_nodes[0]["data"]["age"].should == 31
60
+ new_nodes[1]["data"]["height"].should == "5-11"
61
+ new_nodes[1]["data"]["weight"].should == 215
62
+ end
63
+
64
+ it "is not super slow?" do
65
+ Benchmark.bm do |x|
66
+ x.report( "create 1 node" ) { @neo.create_nodes( 1) }
67
+ x.report( "create 10 nodes") { @neo.create_nodes( 10) }
68
+ x.report("create 100 nodes") { @neo.create_nodes(100) }
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "can get many nodes" do
74
+ it "can get 2 nodes passed in as an array" do
75
+ new_nodes = @neo.create_nodes(2)
76
+ existing_nodes = @neo.get_nodes(new_nodes)
77
+ existing_nodes.should_not be_nil
78
+ existing_nodes.size.should == 2
79
+ end
80
+
81
+ it "can get 2 nodes passed in by commas" do
82
+ new_nodes = @neo.create_nodes(2)
83
+ new_node1 = new_nodes[0]["self"].split('/').last
84
+ new_node2 = new_nodes[1]["self"].split('/').last
85
+ existing_nodes = @neo.get_nodes(new_node1, new_node2)
86
+ existing_nodes.should_not be_nil
87
+ existing_nodes.size.should == 2
88
+ existing_nodes[0]["self"] == new_node1["self"]
89
+ existing_nodes[1]["self"] == new_node2["self"]
90
+ end
91
+
92
+ it "is not super slow?" do
93
+ one_node = @neo.create_nodes( 1)
94
+ ten_nodes = @neo.create_nodes( 10)
95
+ one_hundred_nodes = @neo.create_nodes(100)
96
+
97
+ Benchmark.bm do |x|
98
+ x.report( "get 1 node ") { @neo.get_nodes(one_node) }
99
+ x.report( "get 10 nodes") { @neo.get_nodes(ten_nodes) }
100
+ x.report("get 100 nodes") { @neo.get_nodes(one_hundred_nodes) }
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,23 @@
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
+
9
+ describe "get_nodes" do
10
+ it "can get nodes that exists" do
11
+ existing_nodes = @neo.get_nodes
12
+ existing_nodes.should_not be_nil
13
+ puts existing_nodes.inspect
14
+ end
15
+
16
+ it "can get all nodes that exists the ugly way" do
17
+ new_node = @neo.create_node
18
+ last_node_id = new_node["self"].split('/').last.to_i
19
+ existing_nodes = @neo.get_nodes((1..last_node_id).to_a)
20
+ existing_nodes.should_not be_nil
21
+ end
22
+ end
23
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'neography'
2
2
  require 'fakeweb'
3
+ require 'benchmark'
3
4
 
4
5
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
5
6
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 4
9
- version: 0.0.4
8
+ - 5
9
+ version: 0.0.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Max De Marzi
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-21 00:00:00 -08:00
17
+ date: 2010-12-08 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -112,9 +112,24 @@ files:
112
112
  - examples/linkedin.rb
113
113
  - examples/traversal_example1.rb
114
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
115
125
  - lib/neography/rest.rb
116
126
  - lib/neography/version.rb
117
127
  - neography.gemspec
128
+ - spec/integration/neography_spec.rb
129
+ - spec/integration/node_spec.rb
130
+ - spec/integration/relationship_spec.rb
131
+ - spec/integration/rest_bulk_spec.rb
132
+ - spec/integration/rest_experimental_spec.rb
118
133
  - spec/integration/rest_index_spec.rb
119
134
  - spec/integration/rest_node_spec.rb
120
135
  - spec/integration/rest_path_spec.rb