neography 1.0.9 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
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