neography 1.0.10 → 1.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.travis.yml +1 -1
  2. data/README.md +1 -0
  3. data/lib/neography/connection.rb +45 -34
  4. data/lib/neography/node.rb +1 -1
  5. data/lib/neography/path_traverser.rb +9 -4
  6. data/lib/neography/property_container.rb +16 -4
  7. data/lib/neography/rest.rb +86 -2
  8. data/lib/neography/rest/batch.rb +4 -12
  9. data/lib/neography/rest/cypher.rb +12 -3
  10. data/lib/neography/rest/helpers.rb +12 -0
  11. data/lib/neography/rest/node_labels.rb +60 -0
  12. data/lib/neography/rest/node_relationships.rb +0 -11
  13. data/lib/neography/rest/other_node_relationships.rb +1 -12
  14. data/lib/neography/rest/relationship_types.rb +18 -0
  15. data/lib/neography/rest/schema_indexes.rb +34 -0
  16. data/lib/neography/rest/transactions.rb +83 -0
  17. data/lib/neography/tasks.rb +1 -1
  18. data/lib/neography/version.rb +1 -1
  19. data/spec/integration/node_spec.rb +13 -0
  20. data/spec/integration/rest_batch_spec.rb +11 -15
  21. data/spec/integration/rest_batch_streaming_spec.rb +2 -2
  22. data/spec/integration/rest_gremlin_fail_spec.rb +4 -4
  23. data/spec/integration/rest_header_spec.rb +1 -1
  24. data/spec/integration/rest_labels_spec.rb +131 -0
  25. data/spec/integration/rest_plugin_spec.rb +32 -3
  26. data/spec/integration/rest_relationship_types_spec.rb +18 -0
  27. data/spec/integration/rest_schema_index_spec.rb +32 -0
  28. data/spec/integration/rest_transaction_spec.rb +100 -0
  29. data/spec/spec_helper.rb +8 -1
  30. data/spec/unit/connection_spec.rb +1 -1
  31. data/spec/unit/node_spec.rb +1 -1
  32. data/spec/unit/rest/batch_spec.rb +21 -21
  33. data/spec/unit/rest/labels_spec.rb +73 -0
  34. data/spec/unit/rest/relationship_types_spec.rb +16 -0
  35. data/spec/unit/rest/schema_index_spec.rb +31 -0
  36. data/spec/unit/rest/transactions_spec.rb +44 -0
  37. metadata +22 -2
@@ -37,17 +37,6 @@ module Neography
37
37
  node_relationships
38
38
  end
39
39
 
40
- def parse_direction(direction)
41
- case direction
42
- when :incoming, "incoming", :in, "in"
43
- "in"
44
- when :outgoing, "outgoing", :out, "out"
45
- "out"
46
- else
47
- "all"
48
- end
49
- end
50
-
51
40
  end
52
41
  end
53
42
  end
@@ -36,24 +36,13 @@ module Neography
36
36
  }.merge(relationships).to_json,
37
37
  :headers => json_content_type
38
38
  }
39
- #puts options.inspect
39
+
40
40
  node_relationships = @connection.post(base_path(:id => get_id(id)), options) || []
41
41
 
42
42
  return nil if node_relationships.empty?
43
43
  node_relationships
44
44
  end
45
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
46
  end
58
47
  end
59
48
  end
@@ -0,0 +1,18 @@
1
+ module Neography
2
+ class Rest
3
+ class RelationshipTypes
4
+ extend Neography::Rest::Paths
5
+
6
+ add_path :all, "/relationship/types"
7
+
8
+ def initialize(connection)
9
+ @connection = connection
10
+ end
11
+
12
+ def list
13
+ @connection.get(all_path)
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ module Neography
2
+ class Rest
3
+ class SchemaIndexes
4
+ extend Neography::Rest::Paths
5
+ include Neography::Rest::Helpers
6
+
7
+ add_path :base, "/schema/index/:label"
8
+ add_path :drop, "/schema/index/:label/:index"
9
+
10
+ def initialize(connection)
11
+ @connection = connection
12
+ end
13
+
14
+ def list(label)
15
+ @connection.get(base_path(:label => label))
16
+ end
17
+
18
+ def drop(label, index)
19
+ @connection.delete(drop_path(:label => label, :index => index))
20
+ end
21
+
22
+ def create(label, keys = [])
23
+ options = {
24
+ :body => (
25
+ { :property_keys => keys
26
+ }
27
+ ).to_json,
28
+ :headers => json_content_type
29
+ }
30
+ @connection.post(base_path(:label => label), options)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,83 @@
1
+ module Neography
2
+ class Rest
3
+ class Transactions
4
+ extend Neography::Rest::Paths
5
+ include Neography::Rest::Helpers
6
+
7
+ add_path :base, "/transaction"
8
+ add_path :tx, "/transaction/:id"
9
+ add_path :commit, "/transaction/:id/commit"
10
+
11
+ def initialize(connection)
12
+ @connection = connection
13
+ end
14
+
15
+ def begin(statements = [], commit = "")
16
+ options = {
17
+ :body => (
18
+ convert_cypher(statements)
19
+ ).to_json,
20
+ :headers => json_content_type
21
+ }
22
+ @connection.post(base_path + commit, options)
23
+ end
24
+
25
+ def add(tx, statements = [])
26
+ options = {
27
+ :body => (
28
+ convert_cypher(statements)
29
+ ).to_json,
30
+ :headers => json_content_type
31
+ }
32
+ @connection.post(tx_path(:id => get_id(tx)), options)
33
+ end
34
+
35
+ def commit(tx, statements = [])
36
+ options = {
37
+ :body => (
38
+ convert_cypher(statements)
39
+ ).to_json,
40
+ :headers => json_content_type
41
+ }
42
+ @connection.post(commit_path(:id => get_id(tx)), options)
43
+ end
44
+
45
+ def rollback(tx)
46
+ @connection.delete(tx_path(:id => get_id(tx)))
47
+ end
48
+
49
+ private
50
+
51
+ def get_id(tx)
52
+ return tx if tx.is_a?(Integer)
53
+ return tx.split("/")[-2] if tx.is_a?(String)
54
+ return tx["commit"].split("/")[-2] if tx["commit"]
55
+ raise NeographyError.new("Could not determine transaction id", nil, tx)
56
+ end
57
+
58
+ def convert_cypher(statements)
59
+ array = []
60
+ query = nil
61
+ parameters = nil
62
+ Array(statements).each do |statement|
63
+ if query & parameters
64
+ array << {:statement => query, :parameters => {:props => parameters}}
65
+ query = statement
66
+ parameters = nil
67
+ elsif query & statement.is_a?(String)
68
+ array << {:statement => query}
69
+ query = statement
70
+ parameters = nil
71
+ elsif query & statement.is_a?(Hash)
72
+ array << {:statement => query, :parameters => {:props => parameters}}
73
+ query = nil
74
+ parameters = nil
75
+ end
76
+ query = statement
77
+ end
78
+ array << {:statement => query} if query
79
+ { :statements => array }
80
+ end
81
+ end
82
+ end
83
+ end
@@ -6,7 +6,7 @@ require 'zip/zip'
6
6
  namespace :neo4j do
7
7
  desc "Install Neo4j"
8
8
  task :install, :edition, :version do |t, args|
9
- args.with_defaults(:edition => "community", :version => "1.8.2")
9
+ args.with_defaults(:edition => "community", :version => "1.9")
10
10
  puts "Installing Neo4j-#{args[:edition]}-#{args[:version]}"
11
11
 
12
12
  if OS::Underlying.windows?
@@ -1,3 +1,3 @@
1
1
  module Neography
2
- VERSION = "1.0.10"
2
+ VERSION = "1.0.11"
3
3
  end
@@ -68,6 +68,19 @@ describe Neography::Node do
68
68
  existing_node = Neography::Node.load(@neo, new_node)
69
69
  }.to raise_error(ArgumentError)
70
70
  end
71
+
72
+ it "can get a node that exists via cypher" do
73
+ new_node = Neography::Node.create("age" => 31, "name" => "Max")
74
+ cypher = "START n = node({id}) return n"
75
+ @neo = Neography::Rest.new
76
+ results = @neo.execute_query(cypher, {:id => new_node.neo_id.to_i})
77
+ existing_node = Neography::Node.load(results)
78
+ existing_node.should_not be_nil
79
+ existing_node.neo_id.should_not be_nil
80
+ existing_node.neo_id.should == new_node.neo_id
81
+ end
82
+
83
+
71
84
  end
72
85
 
73
86
  describe "del" do
@@ -255,14 +255,14 @@ describe Neography::Rest do
255
255
  batch_result.first["body"].first["end"].split('/').last.should == node2["self"].split('/').last
256
256
  end
257
257
 
258
- it "can batch gremlin" do
258
+ it "can batch gremlin", :gremlin => true do
259
259
  batch_result = @neo.batch [:execute_script, "g.v(0)"]
260
260
  batch_result.first.should have_key("id")
261
261
  batch_result.first.should have_key("from")
262
262
  batch_result.first["body"]["self"].split('/').last.should == "0"
263
263
  end
264
264
 
265
- it "can batch gremlin with parameters" do
265
+ it "can batch gremlin with parameters", :gremlin => true do
266
266
  new_node = @neo.create_node
267
267
  id = new_node["self"].split('/').last
268
268
  batch_result = @neo.batch [:execute_script, "g.v(id)", {:id => id.to_i}]
@@ -445,38 +445,34 @@ describe Neography::Rest do
445
445
  # See https://github.com/neo4j/community/issues/697
446
446
 
447
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)
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::NeographyError)
453
453
  end
454
454
 
455
455
  end
456
456
 
457
457
  describe "broken queries" do
458
458
  it "should return errors when bad syntax is passed in batch" do
459
-
460
459
  batch_commands = []
461
- # batch_commands << [ :create_unique_node, "person", "ssn", "000-00-0002", {:foo => "bar"} ]
462
460
 
463
- # this doesn't raise error
464
461
  batch_commands << [ :execute_query, "start person_n=node:person(ssn = '000-00-0002')
465
- set bar1 = {foo}",
462
+ set bar1 = {foo}",
466
463
  { :other => "what" }
467
464
  ]
468
465
 
466
+ expect {
467
+ batch_result = @neo.batch *batch_commands
468
+ }.to raise_exception Neography::SyntaxException
469
469
 
470
- # this does raise error
471
470
  expect {
472
471
  @neo.execute_query("start person_n=node:person(ssn = '000-00-0001')
473
472
  set bar = {foo}",
474
473
  { :other => "what" })
475
474
  }.to raise_exception Neography::SyntaxException
476
475
 
477
- expect {
478
- batch_result = @neo.batch *batch_commands
479
- }.to raise_exception Neography::SyntaxException
480
476
 
481
477
  end
482
478
  end
@@ -17,9 +17,9 @@ describe Neography::Rest do
17
17
  batch_result.last["body"]["data"]["name"].should == "Max 999"
18
18
  end
19
19
 
20
- it "can send a 10000 item batch" do
20
+ it "can send a 5000 item batch" do
21
21
  commands = []
22
- 10000.times do |x|
22
+ 5000.times do |x|
23
23
  commands << [:get_node, 0]
24
24
  end
25
25
  batch_result = @neo.batch *commands
@@ -6,7 +6,7 @@ describe Neography::Rest do
6
6
  end
7
7
 
8
8
  describe "don't break gremlin" do
9
- it "can handle node and relationship indexes" do
9
+ it "can handle node and relationship indexes", :gremlin => true do
10
10
  new_node1 = @neo.create_node
11
11
  new_node2 = @neo.create_node
12
12
  new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
@@ -16,7 +16,7 @@ describe Neography::Rest do
16
16
  @neo.add_relationship_to_index("test_index2", key, value, new_relationship)
17
17
  end
18
18
 
19
- it "gremlin works" do
19
+ it "gremlin works", :gremlin => true do
20
20
  root_node = @neo.execute_script("g.v(0)")
21
21
  root_node.should have_key("self")
22
22
  root_node["self"].split('/').last.should == "0"
@@ -25,7 +25,7 @@ describe Neography::Rest do
25
25
 
26
26
 
27
27
  describe "break gremlin" do
28
- it "can can't handle node and relationship indexes with the same name", :break_gremlin => true do
28
+ it "can can't handle node and relationship indexes with the same name", :gremlin => true do
29
29
  new_node1 = @neo.create_node
30
30
  new_node2 = @neo.create_node
31
31
  new_relationship = @neo.create_relationship("friends", new_node1, new_node2)
@@ -35,7 +35,7 @@ describe Neography::Rest do
35
35
  @neo.add_relationship_to_index("test_index3", key, value, new_relationship)
36
36
  end
37
37
 
38
- it "gremlin works" do
38
+ it "gremlin works", :gremlin => true do
39
39
  root_node = @neo.execute_script("g.v(0)")
40
40
  root_node.should have_key("self")
41
41
  root_node["self"].split('/').last.should == "0"
@@ -8,7 +8,7 @@ describe Neography::Connection do
8
8
 
9
9
  it "should add a content type if there's existing headers" do
10
10
  subject.merge_options({:headers => {'Content-Type' => 'foo/bar'}})[:headers].should ==
11
- {'Content-Type' => "foo/bar", "User-Agent" => "Neography/#{Neography::VERSION}"}
11
+ {'Content-Type' => "foo/bar", "User-Agent" => "Neography/#{Neography::VERSION}" , "X-Stream"=>true}
12
12
  end
13
13
 
14
14
  end
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "list_labels" do
9
+ it "can get the labels of the database" do
10
+ @neo.set_label(0, "Person")
11
+ labels = @neo.list_labels
12
+ labels.should include("Person")
13
+ end
14
+ end
15
+
16
+ describe "add_label" do
17
+ it "can add a label to a node" do
18
+ new_node = @neo.create_node
19
+ new_node_id = new_node["self"].split('/').last
20
+ @neo.add_label(new_node_id, "Person")
21
+ labels = @neo.get_node_labels(new_node_id)
22
+ labels.should == ["Person"]
23
+ end
24
+
25
+ it "can add another label to a node" do
26
+ new_node = @neo.create_node
27
+ new_node_id = new_node["self"].split('/').last
28
+ @neo.add_label(new_node_id, "Actor")
29
+ @neo.add_label(new_node_id, "Director")
30
+ labels = @neo.get_node_labels(new_node_id)
31
+ labels.should == ["Actor", "Director"]
32
+ end
33
+
34
+ it "can add multiple labels to a node" do
35
+ new_node = @neo.create_node
36
+ new_node_id = new_node["self"].split('/').last
37
+ @neo.add_label(new_node_id, ["Actor", "Director"])
38
+ labels = @neo.get_node_labels(new_node_id)
39
+ labels.should == ["Actor", "Director"]
40
+ end
41
+ end
42
+
43
+ describe "set_label" do
44
+ it "can set a label to a node" do
45
+ new_node = @neo.create_node
46
+ new_node_id = new_node["self"].split('/').last
47
+ @neo.set_label(new_node_id, "Person")
48
+ labels = @neo.get_node_labels(new_node_id)
49
+ labels.should == ["Person"]
50
+ end
51
+
52
+ it "can set a label to a node that already had a label" do
53
+ new_node = @neo.create_node
54
+ new_node_id = new_node["self"].split('/').last
55
+ @neo.add_label(new_node_id, "Actor")
56
+ @neo.set_label(new_node_id, "Director")
57
+ labels = @neo.get_node_labels(new_node_id)
58
+ labels.should == ["Director"]
59
+ end
60
+
61
+ it "can set multiple labels to a node" do
62
+ new_node = @neo.create_node
63
+ new_node_id = new_node["self"].split('/').last
64
+ @neo.set_label(new_node_id, ["Actor", "Director"])
65
+ labels = @neo.get_node_labels(new_node_id)
66
+ labels.should == ["Actor", "Director"]
67
+ end
68
+ end
69
+
70
+ describe "delete_label" do
71
+ it "can delete a label from a node" do
72
+ new_node = @neo.create_node
73
+ new_node_id = new_node["self"].split('/').last
74
+ @neo.set_label(new_node_id, ["Actor", "Director"])
75
+ @neo.delete_label(new_node_id, "Actor")
76
+ labels = @neo.get_node_labels(new_node_id)
77
+ labels.should == ["Director"]
78
+ end
79
+
80
+ it "can delete a label from a node that doesn't have one" do
81
+ new_node = @neo.create_node
82
+ new_node_id = new_node["self"].split('/').last
83
+ @neo.delete_label(new_node_id, "Actor")
84
+ labels = @neo.get_node_labels(new_node_id)
85
+ labels.should == []
86
+ end
87
+
88
+ it "cannot delete a label from a node that doesn't exist" do
89
+ new_node = @neo.create_node
90
+ new_node_id = new_node["self"].split('/').last
91
+ expect {
92
+ @neo.delete_label(new_node_id.to_i + 1, "Actor")
93
+ }.to raise_error Neography::NodeNotFoundException
94
+ end
95
+ end
96
+
97
+ describe "get_nodes_labeled" do
98
+ it "can get a node with a label" do
99
+ new_node = @neo.create_node
100
+ new_node_id = new_node["self"].split('/').last
101
+ @neo.set_label(new_node_id, ["Actor", "Director"])
102
+ nodes = @neo.get_nodes_labeled("Actor")
103
+ nodes.last["self"].split('/').last.should == new_node_id
104
+ end
105
+
106
+ it "returns an empty array on non-existing label" do
107
+ nodes = @neo.get_nodes_labeled("do_not_exist")
108
+ nodes.should == []
109
+ end
110
+ end
111
+
112
+ describe "find_nodes_labeled" do
113
+ it "can find a node with a label and a property" do
114
+ new_node = @neo.create_node(:name => "max")
115
+ new_node_id = new_node["self"].split('/').last
116
+ @neo.set_label(new_node_id, "clown")
117
+ nodes = @neo.find_nodes_labeled("clown", { :name => "max" })
118
+ nodes.last["self"].split('/').last.should == new_node_id
119
+ end
120
+
121
+ it "returns an empty array on non-existing label property" do
122
+ new_node = @neo.create_node(:name => "max")
123
+ new_node_id = new_node["self"].split('/').last
124
+ @neo.set_label(new_node_id, "clown")
125
+ nodes = @neo.find_nodes_labeled("clown", { :name => "does_not_exist" })
126
+ nodes.should == []
127
+ end
128
+
129
+ end
130
+
131
+ end