diff --git a/lib/neography/rest.rb b/lib/neography/rest.rb index 60a1212..f699065 100644 --- a/lib/neography/rest.rb +++ b/lib/neography/rest.rb @@ -55,8 +55,9 @@ class Rest include NodePaths include Cypher include Gremlin - include Clean + include Batch include Extensions + include Clean extend Forwardable attr_reader :connection @@ -66,7 +67,6 @@ class Rest def initialize(options = ENV['NEO4J_URL'] || {}) @connection = Connection.new(options) - @batch ||= Batch.new(@connection) @spatial ||= Spatial.new(@connection) end @@ -100,16 +100,6 @@ def get_relationship_start_node(rel) def get_relationship_end_node(rel) get_node(rel["end"]) end - - # batch - - def batch(*args) - @batch.execute(*args) - end - - def batch_not_streaming(*args) - @batch.not_streaming(*args) - end # spatial diff --git a/lib/neography/rest/batch.rb b/lib/neography/rest/batch.rb index 36f4a10..0475c3c 100644 --- a/lib/neography/rest/batch.rb +++ b/lib/neography/rest/batch.rb @@ -1,22 +1,15 @@ module Neography class Rest - class Batch - extend Neography::Rest::Paths + module Batch include Neography::Rest::Helpers - - add_path :batch, "/batch" - - def initialize(connection) - @connection ||= connection - end - - def execute(*args) - batch(*args) + + def batch(*args) + do_batch(*args) end private - def batch(*args) + def do_batch(*args) batch = [] Array(args).each_with_index do |c, i| batch << {:id => i }.merge(get_batch(c)) @@ -25,28 +18,28 @@ def batch(*args) :body => batch.to_json, :headers => json_content_type } - @connection.post(batch_path, options) + @connection.post("/batch", options) end def get_batch(args) - if respond_to?(args[0].to_sym, true) - send(args[0].to_sym, *args[1..-1]) + if args[0].class == Symbol + send(("batch_" + args[0].to_s).to_sym, *args[1..-1]) else - raise "Unknown option #{args[0]}" + raise "Unknown option #{args[0]} - #{args}" end end # Nodes - def get_node(id) + def batch_get_node(id) get "/node/%{id}" % {:id => get_id(id)} end - def delete_node(id) + def batch_delete_node(id) delete "/node/%{id}" % {:id => get_id(id)} end - def create_node(body) + def batch_create_node(body) post "/node" do body end @@ -54,7 +47,7 @@ def create_node(body) # NodeIndexes - def create_node_index(name, type = "exact", provider = "lucene", extra_config = nil) + def batch_create_node_index(name, type = "exact", provider = "lucene", extra_config = nil) config = { :type => type, :provider => provider @@ -67,11 +60,11 @@ def create_node_index(name, type = "exact", provider = "lucene", extra_config = end end - def drop_node_index(index) + def batch_drop_node_index(index) delete "/index/node/%{index}?unique" % {:index => index} end - def create_unique_node(index, key, value, properties) + def batch_create_unique_node(index, key, value, properties) post "/index/node/%{index}?unique" % {:index => index} do { :key => key, @@ -81,7 +74,7 @@ def create_unique_node(index, key, value, properties) end end - def add_node_to_index(index, key, value, id, unique = false) + def batch_add_node_to_index(index, key, value, id, unique = false) path = unique ? "/index/node/%{index}?unique" % {:index => index} : "/index/node/%{index}" % {:index => index} post path do { @@ -92,35 +85,35 @@ def add_node_to_index(index, key, value, id, unique = false) end end - def get_node_index(index, key, value) + def batch_get_node_index(index, key, value) get "/index/node/%{index}/%{key}/%{value}" % {:index => index, :key => key, :value => encode(value)} end - def remove_node_from_index(index, key_or_id, value_or_id = nil, id = nil) + def batch_remove_node_from_index(index, key_or_id, value_or_id = nil, id = nil) delete remove_from_index_path("node", index, key_or_id, value_or_id, id) end # NodeProperties - def set_node_property(id, property) + def batch_set_node_property(id, property) put "/node/%{id}/properties/%{property}" % {:id => get_id(id), :property => property.keys.first} do property.values.first end end - def reset_node_properties(id, body) + def batch_reset_node_properties(id, body) put "/node/%{id}/properties" % {:id => get_id(id)} do body end end - def remove_node_property(id, property) + def batch_remove_node_property(id, property) delete "/node/%{id}/properties/%{property}" % {:id => get_id(id), :property => property} end # NodeLabel - def add_label(id, body) + def batch_add_label(id, body) post build_node_uri(id) + "/labels" do body end @@ -128,7 +121,7 @@ def add_label(id, body) # NodeRelationships - def get_node_relationships(id, direction = nil, types = nil) + def batch_get_node_relationships(id, direction = nil, types = nil) if types.nil? get "/node/%{id}/relationships/%{direction}" % {:id => get_id(id), :direction => direction || 'all'} else @@ -138,15 +131,15 @@ def get_node_relationships(id, direction = nil, types = nil) # Relationships - def get_relationship(id) + def batch_get_relationship(id) get "/relationship/%{id}" % {:id => get_id(id)} end - def delete_relationship(id) + def batch_delete_relationship(id) delete "/relationship/%{id}" % {:id => get_id(id)} end - def create_relationship(type, from, to, data = nil) + def batch_create_relationship(type, from, to, data = nil) post build_node_uri(from) + "/relationships" do { :to => build_node_uri(to), @@ -158,7 +151,7 @@ def create_relationship(type, from, to, data = nil) # RelationshipIndexes - def create_unique_relationship(index, key, value, type, from, to, props = nil) + def batch_create_unique_relationship(index, key, value, type, from, to, props = nil) post "/index/relationship/%{index}?unique" % {:index => index} do { :key => key, @@ -171,7 +164,7 @@ def create_unique_relationship(index, key, value, type, from, to, props = nil) end end - def add_relationship_to_index(index, key, value, id) + def batch_add_relationship_to_index(index, key, value, id) post "/index/relationship/%{index}" % {:index => index} do { :uri => build_relationship_uri(id), @@ -181,23 +174,23 @@ def add_relationship_to_index(index, key, value, id) end end - def get_relationship_index(index, key, value) + def batch_get_relationship_index(index, key, value) get "/index/relationship/%{index}/%{key}/%{value}" % {:index => index, :key => key, :value => encode(value)} end - def remove_relationship_from_index(index, key_or_id, value_or_id = nil, id = nil) + def batch_remove_relationship_from_index(index, key_or_id, value_or_id = nil, id = nil) delete remove_from_index_path("relationship", index, key_or_id, value_or_id, id) end # RelationshipProperties - def set_relationship_property(id, property) + def batch_set_relationship_property(id, property) put "/relationship/%{id}/properties/%{property}" % {:id => get_id(id), :property => property.keys.first} do property.values.first end end - def reset_relationship_properties(id, body) + def batch_reset_relationship_properties(id, body) put build_relationship_uri(id) + "/properties" do body end @@ -205,7 +198,7 @@ def reset_relationship_properties(id, body) # Cypher - def execute_query(query, params = nil) + def batch_execute_query(query, params = nil) request = post @connection.cypher_path do { :query => query @@ -219,7 +212,7 @@ def execute_query(query, params = nil) # Gremlin - def execute_script(script, params = nil) + def batch_execute_script(script, params = nil) post @connection.gremlin_path do { :script => script, @@ -242,11 +235,11 @@ def remove_from_index_path(klass, index, key_or_id, value_or_id = nil, id = nil) # Spatial - def get_spatial + def batch_get_spatial get Spatial.index_path end - def add_point_layer(layer, lat = nil, lon = nil) + def batch_add_point_layer(layer, lat = nil, lon = nil) post Spatial.add_simple_point_layer_path do { :layer => layer, @@ -256,7 +249,7 @@ def add_point_layer(layer, lat = nil, lon = nil) end end - def add_editable_layer(layer, format = "WKT", node_property_name = "wkt") + def batch_add_editable_layer(layer, format = "WKT", node_property_name = "wkt") post Spatial.add_editable_layer_path do { :layer => layer, @@ -266,7 +259,7 @@ def add_editable_layer(layer, format = "WKT", node_property_name = "wkt") end end - def get_layer(layer) + def batch_get_layer(layer) post Spatial.get_layer_path do { :layer => layer @@ -274,7 +267,7 @@ def get_layer(layer) end end - def add_geometry_to_layer(layer, geometry) + def batch_add_geometry_to_layer(layer, geometry) post Spatial.add_geometry_to_layer_path do { :layer => layer, @@ -283,7 +276,7 @@ def add_geometry_to_layer(layer, geometry) end end - def edit_geometry_from_layer(layer, geometry, node) + def batch_edit_geometry_from_layer(layer, geometry, node) post Spatial.edit_geometry_from_layer_path do { :layer => layer, @@ -293,7 +286,7 @@ def edit_geometry_from_layer(layer, geometry, node) end end - def add_node_to_layer(layer, node) + def batch_add_node_to_layer(layer, node) post Spatial.add_node_to_layer_path do { :layer => layer, @@ -302,7 +295,7 @@ def add_node_to_layer(layer, node) end end - def find_geometries_in_bbox(layer, minx, maxx, miny, maxy) + def batch_find_geometries_in_bbox(layer, minx, maxx, miny, maxy) post Spatial.find_geometries_in_bbox_path do { :layer => layer, @@ -314,7 +307,7 @@ def find_geometries_in_bbox(layer, minx, maxx, miny, maxy) end end - def find_geometries_within_distance(layer, pointx, pointy, distance) + def batch_find_geometries_within_distance(layer, pointx, pointy, distance) post Spatial.find_geometries_within_distance_path do { :layer => layer, @@ -325,7 +318,7 @@ def find_geometries_within_distance(layer, pointx, pointy, distance) end end - def create_spatial_index(name, type, lat, lon) + def batch_create_spatial_index(name, type, lat, lon) post "/index/node" do { :name => name, @@ -339,7 +332,7 @@ def create_spatial_index(name, type, lat, lon) end end - def add_node_to_spatial_index(index, id) + def batch_add_node_to_spatial_index(index, id) post "/index/node/%{index}" % {:index => index} do { :uri => build_node_uri(id), diff --git a/spec/unit/rest/batch_spec.rb b/spec/unit/rest/batch_spec.rb index 1810c79..8a3d629 100644 --- a/spec/unit/rest/batch_spec.rb +++ b/spec/unit/rest/batch_spec.rb @@ -4,8 +4,7 @@ module Neography class Rest describe Batch do - let(:connection) { double(:gremlin_path => "/gremlin", :cypher_path => "/cypher") } - subject { Batch.new(connection) } + subject { Neography::Rest.new } it "gets nodes" do expected_body = [ @@ -13,8 +12,8 @@ class Rest { "id" => 1, "method" => "GET", "to" => "/node/bar" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:get_node, "foo"], [:get_node, "bar"] + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:get_node, "foo"], [:get_node, "bar"] end it "creates nodes" do @@ -23,8 +22,8 @@ class Rest { "id" => 1, "method" => "POST", "to" => "/node", "body" => { "baz" => "qux" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:create_node, { "foo" => "bar" }], [:create_node, { "baz" => "qux" }] + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:create_node, { "foo" => "bar" }], [:create_node, { "baz" => "qux" }] end it "deletes nodes" do @@ -33,8 +32,8 @@ class Rest { "id" => 1, "method" => "DELETE", "to" => "/node/bar" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:delete_node, "foo"], [:delete_node, "bar"] + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:delete_node, "foo"], [:delete_node, "bar"] end it "creates unique nodes" do @@ -43,8 +42,8 @@ class Rest { "id" => 1, "method" => "POST", "to" => "/index/node/quux?unique", "body" => { "key" => "corge", "value" => "grault", "properties" => "garply" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:create_unique_node, "foo", "bar", "baz", "qux" ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:create_unique_node, "foo", "bar", "baz", "qux" ], [:create_unique_node, "quux", "corge", "grault", "garply"] end @@ -54,8 +53,8 @@ class Rest { "id" => 1, "method" => "POST", "to" => "/index/node/quux", "body" => { "uri" => "{0}", "key" => "corge", "value" => "grault" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:add_node_to_index, "foo", "bar", "baz", "qux" ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:add_node_to_index, "foo", "bar", "baz", "qux" ], [:add_node_to_index, "quux", "corge", "grault", "{0}"] end @@ -65,8 +64,8 @@ class Rest { "id" => 1, "method" => "GET", "to" => "/index/node/qux/quux/corge" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:get_node_index, "foo", "bar", "baz" ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:get_node_index, "foo", "bar", "baz" ], [:get_node_index, "qux", "quux", "corge" ] end @@ -77,8 +76,8 @@ class Rest { "id" => 2, "method" => "DELETE", "to" => "/index/node/index3/key3/value3/id3" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:remove_node_from_index, "index1", "id1", ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:remove_node_from_index, "index1", "id1", ], [:remove_node_from_index, "index2", "key2", "id2" ], [:remove_node_from_index, "index3", "key3", "value3", "id3" ] end @@ -89,8 +88,8 @@ class Rest { "id" => 1, "method" => "PUT", "to" => "/node/index2/properties/key2", "body" => "value2" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:set_node_property, "index1", { "key1" => "value1" } ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:set_node_property, "index1", { "key1" => "value1" } ], [:set_node_property, "index2", { "key2" => "value2" } ] end @@ -100,8 +99,8 @@ class Rest { "id" => 1, "method" => "PUT", "to" => "/node/index2/properties", "body" => { "key2" => "value2" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:reset_node_properties, "index1", { "key1" => "value1" } ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:reset_node_properties, "index1", { "key1" => "value1" } ], [:reset_node_properties, "index2", { "key2" => "value2" } ] end @@ -110,8 +109,8 @@ class Rest { "id" => 0, "method" => "POST", "to" => "{0}/labels", "body" => "foo" }, { "id" => 1, "method" => "POST", "to" => "{0}/labels", "body" => "bar" }, ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:add_label, "{0}", "foo"], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:add_label, "{0}", "foo"], [:add_label, "{0}", "bar"] end @@ -121,8 +120,8 @@ class Rest { "id" => 1, "method" => "GET", "to" => "/node/id2/relationships/all" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:get_node_relationships, "id1", "direction1" ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:get_node_relationships, "id1", "direction1" ], [:get_node_relationships, "id2" ] end @@ -132,8 +131,8 @@ class Rest { "id" => 1, "method" => "GET", "to" => "/relationship/bar" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:get_relationship, "foo"], [:get_relationship, "bar"] + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:get_relationship, "foo"], [:get_relationship, "bar"] end it "creates relationships" do @@ -142,8 +141,8 @@ class Rest { "id" => 1, "method" => "POST", "to" => "{0}/relationships", "body" => { "to" => "{1}", "type" => "type2", "data" => "data2" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:create_relationship, "type1", "from1", "to1", "data1" ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:create_relationship, "type1", "from1", "to1", "data1" ], [:create_relationship, "type2", "{0}", "{1}", "data2" ] end @@ -153,8 +152,8 @@ class Rest { "id" => 1, "method" => "DELETE", "to" => "/relationship/bar" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:delete_relationship, "foo"], [:delete_relationship, "bar"] + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:delete_relationship, "foo"], [:delete_relationship, "bar"] end it "creates unique nodes" do @@ -163,8 +162,8 @@ class Rest { "id" => 1, "method" => "POST", "to" => "/index/relationship/index2?unique", "body" => { "key" => "key2", "value" => "value2", "type" => "type2", "start" => "{0}", "end" => "{1}", "properties" => "properties" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:create_unique_relationship, "index1", "key1", "value1", "type1", "node1", "node2","properties" ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:create_unique_relationship, "index1", "key1", "value1", "type1", "node1", "node2","properties" ], [:create_unique_relationship, "index2", "key2", "value2", "type2", "{0}", "{1}", "properties" ] end @@ -174,8 +173,8 @@ class Rest { "id" => 1, "method" => "POST", "to" => "/index/relationship/index2", "body" => { "uri" => "{0}", "key" => "key2", "value" => "value2" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:add_relationship_to_index, "index1", "key1", "value1", "rel1" ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:add_relationship_to_index, "index1", "key1", "value1", "rel1" ], [:add_relationship_to_index, "index2", "key2", "value2", "{0}"] end @@ -185,8 +184,8 @@ class Rest { "id" => 1, "method" => "GET", "to" => "/index/relationship/qux/quux/corge" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:get_relationship_index, "foo", "bar", "baz" ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:get_relationship_index, "foo", "bar", "baz" ], [:get_relationship_index, "qux", "quux", "corge" ] end @@ -197,8 +196,8 @@ class Rest { "id" => 2, "method" => "DELETE", "to" => "/index/relationship/index3/key3/value3/id3" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:remove_relationship_from_index, "index1", "id1", ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:remove_relationship_from_index, "index1", "id1", ], [:remove_relationship_from_index, "index2", "key2", "id2" ], [:remove_relationship_from_index, "index3", "key3", "value3", "id3" ] end @@ -209,8 +208,8 @@ class Rest { "id" => 1, "method" => "PUT", "to" => "/relationship/index2/properties/key2", "body" => "value2" } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:set_relationship_property, "index1", { "key1" => "value1" } ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:set_relationship_property, "index1", { "key1" => "value1" } ], [:set_relationship_property, "index2", { "key2" => "value2" } ] end @@ -220,30 +219,30 @@ class Rest { "id" => 1, "method" => "PUT", "to" => "{0}/properties", "body" => { "key2" => "value2" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:reset_relationship_properties, "index1", { "key1" => "value1" } ], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:reset_relationship_properties, "index1", { "key1" => "value1" } ], [:reset_relationship_properties, "{0}", { "key2" => "value2" } ] end - it "executes scripts" do + it "batchs scripts" do expected_body = [ - { "id" => 0, "method" => "POST", "to" => "/gremlin", "body" => { "script" => "script1", "params" => "params1" } }, - { "id" => 1, "method" => "POST", "to" => "/gremlin", "body" => { "script" => "script2", "params" => "params2" } } + { "id" => 0, "method" => "POST", "to" => "/ext/GremlinPlugin/graphdb/execute_script", "body" => { "script" => "script1", "params" => "params1" } }, + { "id" => 1, "method" => "POST", "to" => "/ext/GremlinPlugin/graphdb/execute_script", "body" => { "script" => "script2", "params" => "params2" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:execute_script, "script1", "params1"], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:execute_script, "script1", "params1"], [:execute_script, "script2", "params2"] end - it "executes queries" do + it "batchs queries" do expected_body = [ { "id" => 0, "method" => "POST", "to" => "/cypher", "body" => { "query" => "query1", "params" => "params1" } }, { "id" => 1, "method" => "POST", "to" => "/cypher", "body" => { "query" => "query2" } } ] - connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) - subject.execute [:execute_query, "query1", "params1"], + subject.connection.should_receive(:post).with("/batch", json_match(:body, expected_body)) + subject.batch [:execute_query, "query1", "params1"], [:execute_query, "query2" ] end