diff --git a/lib/deja/bridge.rb b/lib/deja/bridge.rb index 02044fb..5ec14e5 100644 --- a/lib/deja/bridge.rb +++ b/lib/deja/bridge.rb @@ -9,41 +9,44 @@ def cypher(&block) Neo4j::Cypher.query(&block) end - def create_node(attributes = {}) - raise Deja::Error::InvalidParameter unless attributes - raise Deja::Error::NoParameter if attributes.empty? - cypher { node.new(attributes).neo_id } - end - - def delete_node(id) - is_index?(id) ? delete_node_by_index(id) : delete_node_by_id(id) + ## these methods take a cypher block context as an argument, + ## it allows us to treat nodes/rels the same regardless of index or id + def node(id, context, return_root = true) + if return_root + is_index?(id) ? context.lookup(id[:index], id[:key], id[:value]).ret : context.node(id).ret + else + is_index?(id) ? context.lookup(id[:index], id[:key], id[:value]) : context.node(id) + end end - def delete_node_by_index(id) - cypher { lookup(id[:index], id[:key], id[:value]).del.both(rel().as(:r).del) } + def rel(id, context, return_root = true) + if return_root + is_index?(id) ? context.lookup_rel(id[:index], id[:key], id[:value]).ret : context.rel(id).ret + else + is_index?(id) ? context.lookup_rel(id[:index], id[:key], id[:value]) : context.rel(id) + end end - def delete_node_by_id(neo_id) - cypher { node(neo_id).del.both(rel().as(:r).del) } + def attach_filter(result, filter = nil) + result.where{|n| n[:type] == filter.to_s.camelize} if filter + result end - def update_node(id, attributes) - is_index?(id) ? update_node_by_index(id, attributes) : update_node_by_id(id, attributes) + def create_node(attributes = {}) + raise Deja::Error::InvalidParameter unless attributes + raise Deja::Error::NoParameter if attributes.empty? + cypher { node.new(attributes).neo_id } end - def update_node_by_id(neo_id, attributes) - cypher do - node(neo_id).tap do |n| - attributes.each do |key, value| - n[key] = value - end - end - end + def delete_node(id) + cypher{ + Deja::Bridge.node(id, self, false).del.both(rel().as(:r).del) + } end - def update_node_by_index(id, attributes) + def update_node(id, attributes) cypher do - lookup(id[:index], id[:key], id[:value]).tap do |n| + Deja::Bridge.node(id, self, false).tap do |n| attributes.each do |key, value| n[key] = value end @@ -52,50 +55,20 @@ def update_node_by_index(id, attributes) end def create_relationship(start_node, end_node, name, attributes = {}) - cypher { create_path{ node(start_node) > rel(name, attributes).as(:r).neo_id.ret > node(end_node)} } - end - - def create_relationship_from_index(start_node, end_node, name, attributes = {}) - cypher { create_path{ lookup(start_node[:index], start_node[:key], start_node[:value]) > rel(name, attributes).as(:r).neo_id.ret > lookup(end_node[:index], end_node[:key], end_node[:value])} } + cypher { create_path{ Deja::Bridge.node(start_node, self, false) > rel(name, attributes).as(:r).neo_id.ret > Deja::Bridge.node(end_node, self, false)} } end - def get_relationship(index_or_id) - is_index?(index_or_id) ? rels_from_index(index_or_id) : rels_from_id(index_or_id) + def get_relationship(id) + cypher { node.ret < Deja::Bridge.rel(id, self) < node.ret } end def get_relationship_from_nodes(start_node, end_node, type) - cypher { node(start_node).ret > rel(type).ret > node(end_node).ret } - end - - def get_relationship_from_node_indexes(start_node, end_node, type) - cypher { lookup(start_node[:index], start_node[:key], start_node[:value]).ret > rel(type).ret > lookup(end_node[:index], end_node[:key], end_node[:value]).ret } - end - - def rels_from_index(index) - cypher { node.ret < lookup_rel(index[:index], index[:key], index[:value]).ret < node.ret } + cypher { Deja::Bridge.node(start_node, self) > rel(type).ret > Deja::Bridge.node(end_node, self) } end - def rels_from_id(id, opts = {}) - cypher { node.ret < rel(id).ret < node.ret } - end - - def update_relationship(index_or_id, opts = {}) - is_index?(index_or_id) ? update_relationship_by_index(index_or_id, opts) : update_relationship_by_id(index_or_id, opts) - end - - def update_relationship_by_index(index, attributes) + def update_relationship(id, attributes = {}) cypher do - lookup_rel(index[:index], index[:key], index[:value]).tap do |r| - attributes.each do |key, value| - r[key] = value - end - end - end - end - - def update_relationship_by_id(id, attributes) - cypher do - rel(id).tap do |r| + Deja::Bridge.rel(id, self).tap do |r| attributes.each do |key, value| r[key] = value end @@ -104,148 +77,40 @@ def update_relationship_by_id(id, attributes) end def delete_relationship(id) - is_index?(id) ? delete_relationship_by_index(id) : delete_relationship_by_id(id) - end - - def delete_relationship_by_index(id) - cypher { lookup_rel(id[:index], id[:key], id[:value]).del } - end - - def delete_relationship_by_id(neo_id) - cypher { rel(neo_id).del } - end - - # includes origin node - def get_node_with_rels(id, opts = {}) - opts[:direction] ||= :both - is_index?(id) ? nodes_from_index(id, opts) : nodes_from_id(id, opts) - end - - def nodes_from_id(neo_id, opts) - return cypher { node(neo_id) } unless opts[:include] - rels = opts[:include] == :all ? nil : opts[:include] - case opts[:direction] - when :out then outgoing_triplet(neo_id, rels) - when :in then incoming_triplet(neo_id, rels) - when :both then in_out_triplet(neo_id, rels) - else false - end - end - - def nodes_from_index(index, opts) - return cypher { lookup(index[:index], index[:key], index[:value])} unless opts[:include] - rels = opts[:include] == :all ? nil : opts[:include] - case opts[:direction] - when :out then idx_outgoing_triplet(index, rels) - when :in then idx_incoming_triplet(index, rels) - when :both then idx_in_out_triplet(index, rels) - else false - end - end - - def rel_or_nil(rels) - rels == :all ? nil : rels - end - - def outgoing_triplet(id, rels = nil) - rels = rel_or_nil(rels) - cypher { node(id).ret.outgoing(rel(*rels).ret).ret } - end - - def idx_outgoing_triplet(index, rels = nil) - rels = rel_or_nil(rels) - cypher { lookup(index[:index], index[:key], index[:value]).ret.outgoing(rel(*rels).ret).ret } - end - - def incoming_triplet(id, rels = nil) - rels = rel_or_nil(rels) - cypher { node(id).ret.incoming(rel(*rels).ret).ret } - end - - def idx_incoming_triplet(index, rels = nil) - rels = rel_or_nil(rels) - cypher { lookup(index[:index], index[:key], index[:value]).ret.incoming(rel(*rels).ret).ret } - end - - def in_out_triplet(id, rels = nil) - rels = rel_or_nil(rels) - cypher { node(id).ret.both(rel(*rels).ret).ret } - end - - def idx_in_out_triplet(index, rels = nil) - rels = rel_or_nil(rels) - cypher { lookup(index[:index], index[:key], index[:value]).ret.both(rel(*rels).ret).ret } + cypher { + Deja::Bridge.rel(id, self, false).del + } end - # does not include origin node def get_related_nodes(id, opts = {}) - opts[:direction] ||= :both - is_index?(id) ? rels_from_node_index(id, opts) : rels_from_node_id(id, opts) - end - - def rels_from_node_id(neo_id, opts) - rels = opts[:include] == :all ? nil : opts[:include] - case opts[:direction] - when :out then outgoing_pair(neo_id, rels, opts[:filter]) - when :in then incoming_pair(neo_id, rels, opts[:filter]) - when :both then in_out_pair(neo_id, rels, opts[:filter]) - else false - end - end - - def rels_from_node_index(index, opts) + opts[:direction] ||= :both + opts[:filter] ||= nil rels = opts[:include] == :all ? nil : opts[:include] case opts[:direction] - when :out then idx_outgoing_pair(index, rels, opts[:filter]) - when :in then idx_incoming_pair(index, rels, opts[:filter]) - when :both then idx_in_out_pair(index, rels, opts[:filter]) + when :out then outgoing_rel(id, rels, opts[:return_root], opts[:filter]) + when :in then incoming_rel(id, rels, opts[:return_root], opts[:filter]) + when :both then in_out_rel(id, rels, opts[:return_root], opts[:filter]) else false end end - def attach_filter(result, filter = nil) - result.where{|n| n[:type] == filter.to_s.camelize} if filter - result - end - - def outgoing_pair(id, rels = nil, filter = nil) - cypher { - r = node(id).outgoing(rel(*rels).ret) - ret Deja::Bridge.attach_filter(r, filter) - } - end - - def idx_outgoing_pair(index, rels = nil, filter = nil) - cypher { - r = lookup(index[:index], index[:key], index[:value]).outgoing(rel(*rels).ret) - ret Deja::Bridge.attach_filter(r, filter) - } - end - - def incoming_pair(id, rels = nil, filter = nil) - cypher { - r = node(id).incoming(rel(*rels).ret) - ret Deja::Bridge.attach_filter(r, filter) - } - end - - def idx_incoming_pair(index, rels = nil, filter = nil) + def outgoing_rel(id, rels = nil, root = nil, filter = nil) cypher { - r = lookup(index[:index], index[:key], index[:value]).incoming(rel(*rels).ret) + r = Deja::Bridge.node(id, self, root).outgoing(rel(*rels).ret) ret Deja::Bridge.attach_filter(r, filter) } end - def in_out_pair(id, rels = nil, filter = nil) + def incoming_rel(id, rels = nil, root = nil, filter = nil) cypher { - r = node(id).both(rel(*rels).ret) + r = Deja::Bridge.node(id, self, root).incoming(rel(*rels).ret) ret Deja::Bridge.attach_filter(r, filter) } end - def idx_in_out_pair(index, rels = nil, filter = nil) + def in_out_rel(id, rels = nil, root = nil, filter = nil) cypher { - r = lookup(index[:index], index[:key], index[:value]) - rel(*rels).ret - node.ret + r = Deja::Bridge.node(id, self, root).both(rel(*rels).ret) ret Deja::Bridge.attach_filter(r, filter) } end diff --git a/lib/deja/query.rb b/lib/deja/query.rb index 09359d7..54f3d0a 100644 --- a/lib/deja/query.rb +++ b/lib/deja/query.rb @@ -46,24 +46,12 @@ def load_relationship_from_nodes(start_node, end_node, type) normalize(result_hash) end - def load_relationship_from_node_indexes(start_node, end_node, type) - cypher_query = Deja::Bridge.get_relationship_from_node_indexes(start_node, end_node, type) - result_hash = Deja.execute_cypher(cypher_query) - normalize(result_hash) - end - def create_relationship(start_node, end_node, label, attributes = {}) cypher_query = Deja::Bridge.create_relationship(start_node, end_node, label, attributes) result_hash = Deja.execute_cypher(cypher_query) rel_id = result_hash['data'].first.first end - def create_relationship_from_index(start_node, end_node, label, attributes = {}) - cypher_query = Deja::Bridge.create_relationship_from_index(start_node, end_node, label, attributes) - result_hash = Deja.execute_cypher(cypher_query) - rel_id = result_hash['data'].first.first - end - def delete_relationship(rel_id) cypher_query = Deja::Bridge.delete_relationship(rel_id) result_hash = Deja.execute_cypher(cypher_query) @@ -76,12 +64,14 @@ def update_relationship(rel_id, attributes = {}) end def load_node_with_args(neo_id, options) - cypher_query = Deja::Bridge.get_node_with_rels(neo_id, options) + options[:return_root] ||= true + cypher_query = Deja::Bridge.get_related_nodes(neo_id, options) result_hash = Deja.execute_cypher(cypher_query) normalize(result_hash) end def load_related_nodes_with_args(neo_id, options) + options[:return_root] ||= false cypher_query = Deja::Bridge.get_related_nodes(neo_id, options) result_hash = Deja.execute_cypher(cypher_query) normalize(result_hash, :lazy) diff --git a/spec/bridge_spec.rb b/spec/bridge_spec.rb index 1cd3815..3b1a5fe 100644 --- a/spec/bridge_spec.rb +++ b/spec/bridge_spec.rb @@ -98,16 +98,6 @@ end end - describe ".get_node_with_rels" do - context "given a node id, and argument" do - it "should return a cypher result" do - query = Deja::Bridge.get_node_with_rels(1, :include => :friends) - query.should be_a(Neo4j::Cypher::Result) - end - end - end - - describe ".get_related_nodes" do context "given a node id" do it "should return a cypher result" do