neography 1.0.9 → 1.0.10

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 CHANGED
@@ -1,5 +1,7 @@
1
1
  coverage
2
2
  .DS_Store
3
+ TAGS
4
+ *.rbc
3
5
  Gemfile.lock
4
6
  .idea
5
7
  *.iml
@@ -10,3 +12,4 @@ pkg/*
10
12
  log/*
11
13
  .rvmrc
12
14
  Gemfile.lock
15
+ *.swp
data/README.md CHANGED
@@ -73,7 +73,7 @@ Neography.configure do |config|
73
73
  config.authentication = nil # 'basic' or 'digest'
74
74
  config.username = nil
75
75
  config.password = nil
76
- config.parser = {:parser => MultiJsonParser}
76
+ config.parser = MultiJsonParser
77
77
  end
78
78
  ```
79
79
 
@@ -1,4 +1,6 @@
1
1
  module Neography
2
+ module WasCreated
3
+ end
2
4
  class Connection
3
5
  USER_AGENT = "Neography/#{Neography::VERSION}"
4
6
 
@@ -13,6 +15,7 @@ module Neography
13
15
  config = merge_configuration(options)
14
16
  save_local_configuration(config)
15
17
  @client = HTTPClient.new
18
+ @client.send_timeout = 1200 # 10 minutes
16
19
  end
17
20
 
18
21
  def configure(protocol, server, port, directory)
@@ -42,6 +45,23 @@ module Neography
42
45
  evaluate_response(@client.post(configuration + path, merge_options(options)[:body], merge_options(options)[:headers]))
43
46
  end
44
47
 
48
+ def post_chunked(path, options={})
49
+ authenticate(configuration + path)
50
+ result = ""
51
+
52
+ response = @client.post(configuration + path, merge_options(options)[:body], merge_options(options)[:headers]) do |chunk|
53
+ result << chunk
54
+ end
55
+
56
+ r = evaluate_chunk_response(response, result)
57
+
58
+ if r.last["status"] > 399
59
+ handle_4xx_500_response(r.last["status"], r.last["body"] || r.last )
60
+ end
61
+
62
+ r
63
+ end
64
+
45
65
  def put(path, options={})
46
66
  authenticate(configuration + path)
47
67
  evaluate_response(@client.put(configuration + path, merge_options(options)[:body], merge_options(options)[:headers]))
@@ -95,23 +115,34 @@ module Neography
95
115
  end
96
116
  end
97
117
 
118
+ def evaluate_chunk_response(response, result)
119
+ code = response.code
120
+ return_result(code, result)
121
+ end
122
+
98
123
  def evaluate_response(response)
99
124
  code = response.code
100
125
  body = response.body
126
+ return_result(code, body)
127
+ end
128
+
129
+ def return_result(code, body)
101
130
  case code
102
131
  when 200
103
132
  @logger.debug "OK" if @log_enabled
104
133
  @parser.json(body) #response.parsed_response
105
134
  when 201
106
135
  @logger.debug "OK, created #{body}" if @log_enabled
107
- @parser.json(body) #response.parsed_response
136
+ r = @parser.json(body) #response.parsed_response
137
+ r.extend(WasCreated)
138
+ r
108
139
  when 204
109
140
  @logger.debug "OK, no content returned" if @log_enabled
110
141
  nil
111
142
  when 400..500
112
143
  handle_4xx_500_response(code, body)
113
144
  nil
114
- end
145
+ end
115
146
  end
116
147
 
117
148
  def handle_4xx_500_response(code, body)
@@ -119,6 +150,10 @@ module Neography
119
150
  parsed_body = {}
120
151
  message = "No error message returned from server."
121
152
  stacktrace = ""
153
+ elsif body.is_a? Hash
154
+ parsed_body = body
155
+ message = parsed_body["message"]
156
+ stacktrace = parsed_body["stacktrace"]
122
157
  else
123
158
  parsed_body = @parser.json(body)
124
159
  message = parsed_body["message"]
@@ -5,9 +5,9 @@ module Neography
5
5
  base.extend(ClassMethods)
6
6
  end
7
7
 
8
- def add_to_index(index, key, value)
8
+ def add_to_index(index, key, value, unique = false)
9
9
  if self.is_a? Neography::Node
10
- self.neo_server.add_node_to_index(index, key, value, self.neo_id)
10
+ self.neo_server.add_node_to_index(index, key, value, self.neo_id, unique)
11
11
  else
12
12
  self.neo_server.add_relationship_to_index(index, key, value, self.neo_id)
13
13
  end
@@ -49,4 +49,4 @@ module Neography
49
49
  end
50
50
 
51
51
  end
52
- end
52
+ end
@@ -10,6 +10,7 @@ require 'neography/rest/auto_indexes'
10
10
  require 'neography/rest/nodes'
11
11
  require 'neography/rest/node_properties'
12
12
  require 'neography/rest/node_relationships'
13
+ require 'neography/rest/other_node_relationships'
13
14
  require 'neography/rest/node_indexes'
14
15
  require 'neography/rest/node_auto_indexes'
15
16
  require 'neography/rest/node_traversal'
@@ -44,6 +45,7 @@ module Neography
44
45
  @nodes = Nodes.new(@connection)
45
46
  @node_properties = NodeProperties.new(@connection)
46
47
  @node_relationships = NodeRelationships.new(@connection)
48
+ @other_node_relationships = OtherNodeRelationships.new(@connection)
47
49
  @node_indexes = NodeIndexes.new(@connection)
48
50
  @node_auto_indexes = NodeAutoIndexes.new(@connection)
49
51
  @node_traversal = NodeTraversal.new(@connection)
@@ -142,7 +144,7 @@ module Neography
142
144
  def get_relationship_end_node(rel)
143
145
  get_node(rel["end"])
144
146
  end
145
-
147
+
146
148
  # relationship properties
147
149
 
148
150
  def get_relationship_properties(id, *properties)
@@ -167,6 +169,10 @@ module Neography
167
169
  @node_relationships.get(id, dir, types)
168
170
  end
169
171
 
172
+ def get_node_relationships_to(id, other_id, dir = "all", types = nil)
173
+ @other_node_relationships.get(id, other_id, dir, Array(types || [nil]))
174
+ end
175
+
170
176
  def create_relationship(type, from, to, props = nil)
171
177
  @node_relationships.create(type, from, to, props)
172
178
  end
@@ -190,8 +196,8 @@ module Neography
190
196
  @node_indexes.create_unique(index, key, value, props)
191
197
  end
192
198
 
193
- def add_node_to_index(index, key, value, id)
194
- @node_indexes.add(index, key, value, id)
199
+ def add_node_to_index(index, key, value, id, unique=false)
200
+ @node_indexes.add(index, key, value, id, unique)
195
201
  end
196
202
  alias_method :add_to_index, :add_node_to_index
197
203
 
@@ -29,8 +29,11 @@ module Neography
29
29
  :body => batch.to_json,
30
30
  :headers => json_content_type.merge(accept_header)
31
31
  }
32
-
33
- @connection.post(batch_path, options)
32
+ if accept_header.empty?
33
+ @connection.post(batch_path, options)
34
+ else
35
+ @connection.post_chunked(batch_path, options)
36
+ end
34
37
  end
35
38
 
36
39
  def get_batch(args)
@@ -69,8 +72,9 @@ module Neography
69
72
  end
70
73
  end
71
74
 
72
- def add_node_to_index(index, key, value, id)
73
- post NodeIndexes.base_path(:index => index) do
75
+ def add_node_to_index(index, key, value, id, unique = false)
76
+ path = unique ? NodeIndexes.unique_path(:index => index) : NodeIndexes.base_path(:index => index)
77
+ post path do
74
78
  {
75
79
  :uri => build_node_uri(id),
76
80
  :key => key,
@@ -31,7 +31,7 @@ module Neography
31
31
  create("#{@index_type}_auto_index", type, provider)
32
32
  end
33
33
 
34
- def add(index, key, value, id)
34
+ def add(index, key, value, id, unique = false)
35
35
  options = {
36
36
  :body => (
37
37
  { :uri => @connection.configuration + "/#{@index_type}/#{get_id(id)}",
@@ -41,8 +41,8 @@ module Neography
41
41
  ).to_json,
42
42
  :headers => json_content_type
43
43
  }
44
-
45
- @connection.post(base_path(:index => index), options)
44
+ path = unique ? unique_path(:index => index) : base_path(:index => index)
45
+ @connection.post(path, options)
46
46
  end
47
47
 
48
48
  def get(index, key, value)
@@ -7,6 +7,7 @@ module Neography
7
7
  add_path :all, "/index/node"
8
8
  add_path :base, "/index/node/:index"
9
9
  add_path :unique, "/index/node/:index?unique"
10
+ add_path :uniqueness, "/index/node/:index?uniqueness=:function"
10
11
  add_path :id, "/index/node/:index/:id"
11
12
  add_path :key, "/index/node/:index/:key/:id"
12
13
  add_path :value, "/index/node/:index/:key/:value/:id"
@@ -30,6 +31,20 @@ module Neography
30
31
  @connection.post(unique_path(:index => index), options)
31
32
  end
32
33
 
34
+ def get_or_create_unique(index, key, value, properties = {})
35
+ options = {
36
+ :body => (
37
+ { :properties => properties,
38
+ :key => key,
39
+ :value => value
40
+ }
41
+ ).to_json,
42
+ :headers => json_content_type
43
+ }
44
+ @connection.post(uniqueness_path(:index => index, :function => 'get_or_create'), options)
45
+
46
+ end
47
+
33
48
  end
34
49
  end
35
50
  end
@@ -0,0 +1,59 @@
1
+ module Neography
2
+ class Rest
3
+ class OtherNodeRelationships
4
+ extend Neography::Rest::Paths
5
+ include Neography::Rest::Helpers
6
+
7
+ add_path :base, "/node/:id/traverse/relationship"
8
+
9
+ def initialize(connection)
10
+ @connection = connection
11
+ end
12
+
13
+ def get(id, other_id, direction = "all", types = [nil])
14
+
15
+ body = case parse_direction(direction)
16
+ when "all"
17
+ "position.endNode().getId() == " + get_id(other_id)
18
+ when "in"
19
+ "position.length() > 0 && position.lastRelationship().getStartNode().getId() == " + get_id(other_id)
20
+ when "out"
21
+ "position.length() > 0 && position.lastRelationship().getEndNode().getId() == " + get_id(other_id)
22
+ end
23
+
24
+ relationships = {:relationships => types.map{|row| Hash[{:type => row}].merge({:direction => parse_direction(direction)})} }
25
+
26
+ if types.first.nil?
27
+ relationships = {}
28
+ end
29
+
30
+ options = {
31
+ :body => {:order => "breadth_first",
32
+ :uniqueness => "relationship_global",
33
+ :max_depth => 1,
34
+ :return_filter => {:language => "javascript",
35
+ :body => body }
36
+ }.merge(relationships).to_json,
37
+ :headers => json_content_type
38
+ }
39
+ #puts options.inspect
40
+ node_relationships = @connection.post(base_path(:id => get_id(id)), options) || []
41
+
42
+ return nil if node_relationships.empty?
43
+ node_relationships
44
+ end
45
+
46
+ def parse_direction(direction)
47
+ case direction
48
+ when :incoming, "incoming", :in, "in"
49
+ "in"
50
+ when :outgoing, "outgoing", :out, "out"
51
+ "out"
52
+ else
53
+ "all"
54
+ end
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -57,14 +57,31 @@ namespace :neo4j do
57
57
  puts "Starting Neo4j..."
58
58
  if OS::Underlying.windows?
59
59
  if %x[reg query "HKU\\S-1-5-19"].size > 0
60
- %x[neo4j/bin/Neo4j.bat start] #start service
60
+ value = %x[neo4j/bin/Neo4j.bat start] #start service
61
61
  else
62
62
  puts "Starting Neo4j directly, not as a service."
63
- %x[neo4j/bin/Neo4j.bat]
63
+ value = %x[neo4j/bin/Neo4j.bat]
64
64
  end
65
65
  else
66
- %x[neo4j/bin/neo4j start]
66
+ value = %x[neo4j/bin/neo4j start]
67
67
  end
68
+ puts value
69
+ end
70
+
71
+ desc "Start the Neo4j Server in the background"
72
+ task :start_no_wait do
73
+ puts "Starting Neo4j in the background..."
74
+ if OS::Underlying.windows?
75
+ if %x[reg query "HKU\\S-1-5-19"].size > 0
76
+ value = %x[neo4j/bin/Neo4j.bat start-no-wait] #start service
77
+ else
78
+ puts "Starting Neo4j directly, not as a service."
79
+ value = %x[neo4j/bin/Neo4j.bat start-no-wait]
80
+ end
81
+ else
82
+ value = %x[neo4j/bin/neo4j start-no-wait]
83
+ end
84
+ puts value
68
85
  end
69
86
 
70
87
  desc "Stop the Neo4j Server"
@@ -72,13 +89,14 @@ namespace :neo4j do
72
89
  puts "Stopping Neo4j..."
73
90
  if OS::Underlying.windows?
74
91
  if %x[reg query "HKU\\S-1-5-19"].size > 0
75
- %x[neo4j/bin/Neo4j.bat stop] #stop service
92
+ value = %x[neo4j/bin/Neo4j.bat stop] #stop service
76
93
  else
77
94
  puts "You do not have administrative rights to stop the Neo4j Service"
78
95
  end
79
96
  else
80
- %x[neo4j/bin/neo4j stop]
97
+ value = %x[neo4j/bin/neo4j stop]
81
98
  end
99
+ puts value
82
100
  end
83
101
 
84
102
  desc "Restart the Neo4j Server"
@@ -1,3 +1,3 @@
1
1
  module Neography
2
- VERSION = "1.0.9"
2
+ VERSION = "1.0.10"
3
3
  end
data/neography.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
25
25
  s.add_development_dependency "coveralls"
26
26
  s.add_dependency "httpclient", ">= 2.3.3"
27
27
  s.add_dependency "rake", ">= 0.8.7"
28
- s.add_dependency "json", ">= 1.6.0"
28
+ s.add_dependency "json", ">= 1.7.7"
29
29
  s.add_dependency "os", ">= 0.9.6"
30
30
  s.add_dependency "rubyzip", ">= 0.9.7"
31
31
  s.add_dependency "multi_json", ">= 1.3.2"
@@ -9,6 +9,13 @@ describe Neography::Index do
9
9
  new_node.add_to_index("node_test_index", key, value)
10
10
  end
11
11
 
12
+ it "can add a node to an index uniquely" do
13
+ new_node = Neography::Node.create
14
+ key = generate_text(6)
15
+ value = generate_text
16
+ new_node.add_to_index("node_test_index", key, value, true)
17
+ end
18
+
12
19
  it "can add a relationship to an index" do
13
20
  node1 = Neography::Node.create
14
21
  node2 = Neography::Node.create
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neography::Rest, :slow => true do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "can perform" do
9
+ it "is fast" do
10
+ Benchmark.bm do |x|
11
+ x.report(" 100 Times") { 100.times { @neo.create_node } }
12
+ x.report(" 500 Times") { 500.times { @neo.create_node } }
13
+ x.report("1000 Times") { 1000.times { @neo.create_node } }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -441,16 +441,44 @@ describe Neography::Rest do
441
441
  [:create_relationship, "has", "{0}", "{2}", {}]
442
442
  batch_result.should_not be_nil
443
443
 
444
-
445
- batch_result = @neo.batch [:create_unique_node, "person", "ssn", "000-00-0001", {:first_name=>"Jane", :last_name=>"Doe", :ssn=>"000-00-0001", :_type=>"Person", :created_at=>1335269478}],
446
- [:add_node_to_index, "person_ssn", "ssn", "000-00-0001", "{0}"],
447
- [:create_node, {:street1=>"94437 Kemmer Crossing", :street2=>"Apt. 333", :city=>"Abshireton", :state=>"AA", :zip=>"65820", :_type=>"Address", :created_at=>1335269478}],
448
- [:create_relationship, "has", "{0}", "{2}", {}]
449
444
  # create_unique_node is returning an index result, not a node, so we can't do this yet.
450
445
  # See https://github.com/neo4j/community/issues/697
451
- batch_result.should_not be_nil
446
+
447
+ expect {
448
+ batch_result = @neo.batch [:create_unique_node, "person", "ssn", "000-00-0001", {:first_name=>"Jane", :last_name=>"Doe", :ssn=>"000-00-0001", :_type=>"Person", :created_at=>1335269478}],
449
+ [:add_node_to_index, "person_ssn", "ssn", "000-00-0001", "{0}"],
450
+ [:create_node, {:street1=>"94437 Kemmer Crossing", :street2=>"Apt. 333", :city=>"Abshireton", :state=>"AA", :zip=>"65820", :_type=>"Address", :created_at=>1335269478}],
451
+ [:create_relationship, "has", "{0}", "{2}", {}]
452
+ }.to raise_error(Neography::BadInputException)
452
453
  end
453
454
 
454
455
  end
455
456
 
457
+ describe "broken queries" do
458
+ it "should return errors when bad syntax is passed in batch" do
459
+
460
+ batch_commands = []
461
+ # batch_commands << [ :create_unique_node, "person", "ssn", "000-00-0002", {:foo => "bar"} ]
462
+
463
+ # this doesn't raise error
464
+ batch_commands << [ :execute_query, "start person_n=node:person(ssn = '000-00-0002')
465
+ set bar1 = {foo}",
466
+ { :other => "what" }
467
+ ]
468
+
469
+
470
+ # this does raise error
471
+ expect {
472
+ @neo.execute_query("start person_n=node:person(ssn = '000-00-0001')
473
+ set bar = {foo}",
474
+ { :other => "what" })
475
+ }.to raise_exception Neography::SyntaxException
476
+
477
+ expect {
478
+ batch_result = @neo.batch *batch_commands
479
+ }.to raise_exception Neography::SyntaxException
480
+
481
+ end
482
+ end
483
+
456
484
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "streaming" do
9
+
10
+ it "can send a 1000 item batch" do
11
+ commands = []
12
+ 1000.times do |x|
13
+ commands << [:create_node, {"name" => "Max " + x.to_s}]
14
+ end
15
+ batch_result = @neo.batch *commands
16
+ batch_result.first["body"]["data"]["name"].should == "Max 0"
17
+ batch_result.last["body"]["data"]["name"].should == "Max 999"
18
+ end
19
+
20
+ it "can send a 10000 item batch" do
21
+ commands = []
22
+ 10000.times do |x|
23
+ commands << [:get_node, 0]
24
+ end
25
+ batch_result = @neo.batch *commands
26
+ batch_result.first["body"]["self"].split('/').last.should == "0"
27
+ batch_result.last["body"]["self"].split('/').last.should == "0"
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "get_relationship" do
9
+ it "can get a relationship that exists" do
10
+ new_node1 = @neo.create_node
11
+ new_node2 = @neo.create_node
12
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
13
+ existing_relationships = @neo.get_node_relationships_to(new_node1, new_node2)
14
+ existing_relationships[0].should_not be_nil
15
+ existing_relationships[0].should have_key("self")
16
+ existing_relationships[0]["self"].should == new_relationship["self"]
17
+ end
18
+
19
+ it "returns nil if it tries to get a relationship that does not exist" do
20
+ new_node1 = @neo.create_node
21
+ new_node2 = @neo.create_node
22
+ new_node3 = @neo.create_node
23
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
24
+ existing_relationship = @neo.get_node_relationships_to(new_node1, new_node3)
25
+ existing_relationship.should be_nil
26
+ end
27
+ end
28
+
29
+ describe "get_node_relationships" do
30
+ it "can get a node's relationship" do
31
+ new_node1 = @neo.create_node
32
+ new_node2 = @neo.create_node
33
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
34
+ relationships = @neo.get_node_relationships_to(new_node1, new_node2)
35
+ relationships.should_not be_nil
36
+ relationships[0]["start"].should == new_node1["self"]
37
+ relationships[0]["end"].should == new_node2["self"]
38
+ relationships[0]["type"].should == "friends"
39
+ relationships[0]["data"]["met"].should == "college"
40
+ relationships[0]["data"]["since"].should == '10-1-2005'
41
+ end
42
+
43
+ it "can get a node's multiple relationships" do
44
+ new_node1 = @neo.create_node
45
+ new_node2 = @neo.create_node
46
+ new_node3 = @neo.create_node
47
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
48
+ new_relationship = @neo.create_relationship("enemies", new_node1, new_node2, {"since" => '10-2-2010', "met" => "work"})
49
+ relationships = @neo.get_node_relationships_to(new_node1, new_node2)
50
+ relationships.should_not be_nil
51
+ relationships[0]["start"].should == new_node1["self"]
52
+ relationships[0]["end"].should == new_node2["self"]
53
+ relationships[0]["type"].should == "friends"
54
+ relationships[0]["data"]["met"].should == "college"
55
+ relationships[0]["data"]["since"].should == '10-1-2005'
56
+ relationships[1]["start"].should == new_node1["self"]
57
+ relationships[1]["end"].should == new_node2["self"]
58
+ relationships[1]["type"].should == "enemies"
59
+ relationships[1]["data"]["met"].should == "work"
60
+ relationships[1]["data"]["since"].should == '10-2-2010'
61
+ end
62
+
63
+ it "can get all of a node's outgoing relationship" do
64
+ new_node1 = @neo.create_node
65
+ new_node2 = @neo.create_node
66
+ new_node3 = @neo.create_node
67
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
68
+ new_relationship = @neo.create_relationship("enemies", new_node2, new_node1, {"since" => '10-2-2010', "met" => "work"})
69
+ relationships = @neo.get_node_relationships_to(new_node1, new_node2, "out")
70
+ relationships.should_not be_nil
71
+ relationships[0]["start"].should == new_node1["self"]
72
+ relationships[0]["end"].should == new_node2["self"]
73
+ relationships[0]["type"].should == "friends"
74
+ relationships[0]["data"]["met"].should == "college"
75
+ relationships[0]["data"]["since"].should == '10-1-2005'
76
+ relationships[1].should be_nil
77
+ end
78
+
79
+ it "can get all of a node's incoming relationship" do
80
+ new_node1 = @neo.create_node
81
+ new_node2 = @neo.create_node
82
+ new_node3 = @neo.create_node
83
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
84
+ new_relationship = @neo.create_relationship("enemies", new_node3, new_node1, {"since" => '10-2-2010', "met" => "work"})
85
+ relationships = @neo.get_node_relationships_to(new_node1, new_node3, "in")
86
+ relationships.should_not be_nil
87
+ relationships[0]["start"].should == new_node3["self"]
88
+ relationships[0]["end"].should == new_node1["self"]
89
+ relationships[0]["type"].should == "enemies"
90
+ relationships[0]["data"]["met"].should == "work"
91
+ relationships[0]["data"]["since"].should == '10-2-2010'
92
+ relationships[1].should be_nil
93
+ end
94
+
95
+ it "can get a specific type of node relationships" do
96
+ new_node1 = @neo.create_node
97
+ new_node2 = @neo.create_node
98
+ new_node3 = @neo.create_node
99
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
100
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node3, {"since" => '10-2-2010', "met" => "work"})
101
+ relationships = @neo.get_node_relationships_to(new_node1, new_node2, "all", "friends")
102
+ relationships.should_not be_nil
103
+ relationships[0]["start"].should == new_node1["self"]
104
+ relationships[0]["end"].should == new_node2["self"]
105
+ relationships[0]["type"].should == "friends"
106
+ relationships[0]["data"]["met"].should == "college"
107
+ relationships[0]["data"]["since"].should == '10-1-2005'
108
+ relationships[1].should be_nil
109
+ end
110
+
111
+ it "can get a specific type and direction of a node relationships" do
112
+ new_node1 = @neo.create_node
113
+ new_node2 = @neo.create_node
114
+ new_node3 = @neo.create_node
115
+ new_node4 = @neo.create_node
116
+ new_relationship = @neo.create_relationship("friends", new_node1, new_node2, {"since" => '10-1-2005', "met" => "college"})
117
+ new_relationship = @neo.create_relationship("enemies", new_node1, new_node3, {"since" => '10-2-2010', "met" => "work"})
118
+ new_relationship = @neo.create_relationship("enemies", new_node4, new_node1, {"since" => '10-3-2010', "met" => "gym"})
119
+ relationships = @neo.get_node_relationships_to(new_node1, new_node4, "in", "enemies")
120
+ relationships.should_not be_nil
121
+ relationships[0]["start"].should == new_node4["self"]
122
+ relationships[0]["end"].should == new_node1["self"]
123
+ relationships[0]["type"].should == "enemies"
124
+ relationships[0]["data"]["met"].should == "gym"
125
+ relationships[0]["data"]["since"].should == '10-3-2010'
126
+ relationships[1].should be_nil
127
+ end
128
+
129
+ it "returns nil if there are no relationships" do
130
+ new_node1 = @neo.create_node
131
+ new_node2 = @neo.create_node
132
+ relationships = @neo.get_node_relationships_to(new_node1, new_node2)
133
+ relationships.should be_nil
134
+ end
135
+ end
136
+
137
+ end
@@ -13,7 +13,7 @@ module Neography
13
13
  { "id" => 1, "method" => "GET", "to" => "/node/bar" }
14
14
  ]
15
15
 
16
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
16
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
17
17
  subject.execute [:get_node, "foo"], [:get_node, "bar"]
18
18
  end
19
19
 
@@ -23,7 +23,7 @@ module Neography
23
23
  { "id" => 1, "method" => "POST", "to" => "/node", "body" => { "baz" => "qux" } }
24
24
  ]
25
25
 
26
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
26
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
27
27
  subject.execute [:create_node, { "foo" => "bar" }], [:create_node, { "baz" => "qux" }]
28
28
  end
29
29
 
@@ -33,7 +33,7 @@ module Neography
33
33
  { "id" => 1, "method" => "DELETE", "to" => "/node/bar" }
34
34
  ]
35
35
 
36
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
36
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
37
37
  subject.execute [:delete_node, "foo"], [:delete_node, "bar"]
38
38
  end
39
39
 
@@ -43,7 +43,7 @@ module Neography
43
43
  { "id" => 1, "method" => "POST", "to" => "/index/node/quux?unique", "body" => { "key" => "corge", "value" => "grault", "properties" => "garply" } }
44
44
  ]
45
45
 
46
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
46
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
47
47
  subject.execute [:create_unique_node, "foo", "bar", "baz", "qux" ],
48
48
  [:create_unique_node, "quux", "corge", "grault", "garply"]
49
49
  end
@@ -54,7 +54,7 @@ module Neography
54
54
  { "id" => 1, "method" => "POST", "to" => "/index/node/quux", "body" => { "uri" => "{0}", "key" => "corge", "value" => "grault" } }
55
55
  ]
56
56
 
57
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
57
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
58
58
  subject.execute [:add_node_to_index, "foo", "bar", "baz", "qux" ],
59
59
  [:add_node_to_index, "quux", "corge", "grault", "{0}"]
60
60
  end
@@ -65,7 +65,7 @@ module Neography
65
65
  { "id" => 1, "method" => "GET", "to" => "/index/node/qux/quux/corge" }
66
66
  ]
67
67
 
68
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
68
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
69
69
  subject.execute [:get_node_index, "foo", "bar", "baz" ],
70
70
  [:get_node_index, "qux", "quux", "corge" ]
71
71
  end
@@ -77,7 +77,7 @@ module Neography
77
77
  { "id" => 2, "method" => "DELETE", "to" => "/index/node/index3/key3/value3/id3" }
78
78
  ]
79
79
 
80
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
80
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
81
81
  subject.execute [:remove_node_from_index, "index1", "id1", ],
82
82
  [:remove_node_from_index, "index2", "key2", "id2" ],
83
83
  [:remove_node_from_index, "index3", "key3", "value3", "id3" ]
@@ -89,7 +89,7 @@ module Neography
89
89
  { "id" => 1, "method" => "PUT", "to" => "/node/index2/properties/key2", "body" => "value2" }
90
90
  ]
91
91
 
92
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
92
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
93
93
  subject.execute [:set_node_property, "index1", { "key1" => "value1" } ],
94
94
  [:set_node_property, "index2", { "key2" => "value2" } ]
95
95
  end
@@ -100,7 +100,7 @@ module Neography
100
100
  { "id" => 1, "method" => "PUT", "to" => "/node/index2/properties", "body" => { "key2" => "value2" } }
101
101
  ]
102
102
 
103
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
103
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
104
104
  subject.execute [:reset_node_properties, "index1", { "key1" => "value1" } ],
105
105
  [:reset_node_properties, "index2", { "key2" => "value2" } ]
106
106
  end
@@ -111,7 +111,7 @@ module Neography
111
111
  { "id" => 1, "method" => "GET", "to" => "/node/id2/relationships/all" }
112
112
  ]
113
113
 
114
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
114
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
115
115
  subject.execute [:get_node_relationships, "id1", "direction1" ],
116
116
  [:get_node_relationships, "id2" ]
117
117
  end
@@ -122,7 +122,7 @@ module Neography
122
122
  { "id" => 1, "method" => "GET", "to" => "/relationship/bar" }
123
123
  ]
124
124
 
125
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
125
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
126
126
  subject.execute [:get_relationship, "foo"], [:get_relationship, "bar"]
127
127
  end
128
128
 
@@ -132,7 +132,7 @@ module Neography
132
132
  { "id" => 1, "method" => "POST", "to" => "{0}/relationships", "body" => { "to" => "{1}", "type" => "type2", "data" => "data2" } }
133
133
  ]
134
134
 
135
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
135
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
136
136
  subject.execute [:create_relationship, "type1", "from1", "to1", "data1" ],
137
137
  [:create_relationship, "type2", "{0}", "{1}", "data2" ]
138
138
  end
@@ -143,7 +143,7 @@ module Neography
143
143
  { "id" => 1, "method" => "DELETE", "to" => "/relationship/bar" }
144
144
  ]
145
145
 
146
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
146
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
147
147
  subject.execute [:delete_relationship, "foo"], [:delete_relationship, "bar"]
148
148
  end
149
149
 
@@ -153,7 +153,7 @@ module Neography
153
153
  { "id" => 1, "method" => "POST", "to" => "/index/relationship/index2?unique", "body" => { "key" => "key2", "value" => "value2", "type" => "type2", "start" => "{0}", "end" => "{1}" } }
154
154
  ]
155
155
 
156
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
156
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
157
157
  subject.execute [:create_unique_relationship, "index1", "key1", "value1", "type1", "node1", "node2" ],
158
158
  [:create_unique_relationship, "index2", "key2", "value2", "type2", "{0}", "{1}" ]
159
159
  end
@@ -164,7 +164,7 @@ module Neography
164
164
  { "id" => 1, "method" => "POST", "to" => "/index/relationship/index2", "body" => { "uri" => "{0}", "key" => "key2", "value" => "value2" } }
165
165
  ]
166
166
 
167
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
167
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
168
168
  subject.execute [:add_relationship_to_index, "index1", "key1", "value1", "rel1" ],
169
169
  [:add_relationship_to_index, "index2", "key2", "value2", "{0}"]
170
170
  end
@@ -175,7 +175,7 @@ module Neography
175
175
  { "id" => 1, "method" => "GET", "to" => "/index/relationship/qux/quux/corge" }
176
176
  ]
177
177
 
178
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
178
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
179
179
  subject.execute [:get_relationship_index, "foo", "bar", "baz" ],
180
180
  [:get_relationship_index, "qux", "quux", "corge" ]
181
181
  end
@@ -187,7 +187,7 @@ module Neography
187
187
  { "id" => 2, "method" => "DELETE", "to" => "/index/relationship/index3/key3/value3/id3" }
188
188
  ]
189
189
 
190
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
190
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
191
191
  subject.execute [:remove_relationship_from_index, "index1", "id1", ],
192
192
  [:remove_relationship_from_index, "index2", "key2", "id2" ],
193
193
  [:remove_relationship_from_index, "index3", "key3", "value3", "id3" ]
@@ -199,7 +199,7 @@ module Neography
199
199
  { "id" => 1, "method" => "PUT", "to" => "/relationship/index2/properties/key2", "body" => "value2" }
200
200
  ]
201
201
 
202
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
202
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
203
203
  subject.execute [:set_relationship_property, "index1", { "key1" => "value1" } ],
204
204
  [:set_relationship_property, "index2", { "key2" => "value2" } ]
205
205
  end
@@ -210,7 +210,7 @@ module Neography
210
210
  { "id" => 1, "method" => "PUT", "to" => "{0}/properties", "body" => { "key2" => "value2" } }
211
211
  ]
212
212
 
213
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
213
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
214
214
  subject.execute [:reset_relationship_properties, "index1", { "key1" => "value1" } ],
215
215
  [:reset_relationship_properties, "{0}", { "key2" => "value2" } ]
216
216
  end
@@ -221,7 +221,7 @@ module Neography
221
221
  { "id" => 1, "method" => "POST", "to" => "/gremlin", "body" => { "script" => "script2", "params" => "params2" } }
222
222
  ]
223
223
 
224
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
224
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
225
225
  subject.execute [:execute_script, "script1", "params1"],
226
226
  [:execute_script, "script2", "params2"]
227
227
  end
@@ -232,7 +232,7 @@ module Neography
232
232
  { "id" => 1, "method" => "POST", "to" => "/cypher", "body" => { "query" => "query2" } }
233
233
  ]
234
234
 
235
- connection.should_receive(:post).with("/batch", json_match(:body, expected_body))
235
+ connection.should_receive(:post_chunked).with("/batch", json_match(:body, expected_body))
236
236
  subject.execute [:execute_query, "query1", "params1"],
237
237
  [:execute_query, "query2" ]
238
238
  end
@@ -51,6 +51,16 @@ module Neography
51
51
  subject.create_unique("some_index", "key", "value", "properties")
52
52
  end
53
53
 
54
+ it "gets or creates a unique node in an index" do
55
+ expected_body = {
56
+ "properties" => "properties",
57
+ "key" => "key",
58
+ "value" => "value"
59
+ }
60
+ connection.should_receive(:post).with("/index/node/some_index?uniqueness=get_or_create", json_match(:body, expected_body))
61
+ subject.get_or_create_unique("some_index", "key", "value", "properties")
62
+ end
63
+
54
64
  it "adds a node to an index" do
55
65
  expected_body = {
56
66
  "uri" => "http://configuration/node/42",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neography
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-21 00:00:00.000000000 Z
12
+ date: 2013-05-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -114,7 +114,7 @@ dependencies:
114
114
  requirements:
115
115
  - - ! '>='
116
116
  - !ruby/object:Gem::Version
117
- version: 1.6.0
117
+ version: 1.7.7
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,7 +122,7 @@ dependencies:
122
122
  requirements:
123
123
  - - ! '>='
124
124
  - !ruby/object:Gem::Version
125
- version: 1.6.0
125
+ version: 1.7.7
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: os
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -227,6 +227,7 @@ files:
227
227
  - lib/neography/rest/node_relationships.rb
228
228
  - lib/neography/rest/node_traversal.rb
229
229
  - lib/neography/rest/nodes.rb
230
+ - lib/neography/rest/other_node_relationships.rb
230
231
  - lib/neography/rest/paths.rb
231
232
  - lib/neography/rest/properties.rb
232
233
  - lib/neography/rest/relationship_auto_indexes.rb
@@ -243,14 +244,17 @@ files:
243
244
  - spec/integration/node_relationship_spec.rb
244
245
  - spec/integration/node_spec.rb
245
246
  - spec/integration/parsing_spec.rb
247
+ - spec/integration/performance_spec.rb
246
248
  - spec/integration/relationship_spec.rb
247
249
  - spec/integration/rest_batch_spec.rb
250
+ - spec/integration/rest_batch_streaming_spec.rb
248
251
  - spec/integration/rest_bulk_spec.rb
249
252
  - spec/integration/rest_experimental_spec.rb
250
253
  - spec/integration/rest_gremlin_fail_spec.rb
251
254
  - spec/integration/rest_header_spec.rb
252
255
  - spec/integration/rest_index_spec.rb
253
256
  - spec/integration/rest_node_spec.rb
257
+ - spec/integration/rest_other_node_relationship_spec.rb
254
258
  - spec/integration/rest_path_spec.rb
255
259
  - spec/integration/rest_plugin_spec.rb
256
260
  - spec/integration/rest_relationship_spec.rb
@@ -312,14 +316,17 @@ test_files:
312
316
  - spec/integration/node_relationship_spec.rb
313
317
  - spec/integration/node_spec.rb
314
318
  - spec/integration/parsing_spec.rb
319
+ - spec/integration/performance_spec.rb
315
320
  - spec/integration/relationship_spec.rb
316
321
  - spec/integration/rest_batch_spec.rb
322
+ - spec/integration/rest_batch_streaming_spec.rb
317
323
  - spec/integration/rest_bulk_spec.rb
318
324
  - spec/integration/rest_experimental_spec.rb
319
325
  - spec/integration/rest_gremlin_fail_spec.rb
320
326
  - spec/integration/rest_header_spec.rb
321
327
  - spec/integration/rest_index_spec.rb
322
328
  - spec/integration/rest_node_spec.rb
329
+ - spec/integration/rest_other_node_relationship_spec.rb
323
330
  - spec/integration/rest_path_spec.rb
324
331
  - spec/integration/rest_plugin_spec.rb
325
332
  - spec/integration/rest_relationship_spec.rb