require 'neo4j/traversal/filter_predicate' require 'neo4j/traversal/prune_evaluator' require 'neo4j/traversal/rel_expander' require 'neo4j/traversal/traverser' module Neo4j # Contains methods that are mixin for Neo4j::Node # They all return Neo4j::Traversal::Traverser # See the {Neo4j.rb Guide: Traversing Relationships and Nodes}[http://neo4j.rubyforge.org/guides/traverser.html] # module Traversal include ToJava # A more powerful alternative of #outgoing, #incoming and #both method. # You can use this method for example to only traverse nodes based on properties on the relationships # # ==== Example # # some_node.expand { |n| n._rels.find_all { |r| r[:age] > 5 } }.depth(:all).to_a # # The above traverse all relationships with a property of age > 5 # # See http://neo4j.rubyforge.org/guides/traverser.html # def expand(&expander) Traverser.new(self).expander(&expander) end # Returns the outgoing nodes for this node. # # ==== Returns # a Neo4j::NodeTraverser which can be used to further specify which nodes should be included # in traversal by using the depth, filter and prune methods. # # ==== Examples # # Find all my friends (nodes of depth 1 of type friends) # me.outgoing(:friends).each {|friend| puts friend.name} # # # A possible faster way, avoid loading wrapper Ruby classes, instead use raw java neo4j node objects # me.outgoing(:friends).raw.each {|friend| puts friend[:name]} # # # Find all my friends and their friends (nodes of depth 1 of type friends) # # me.outgoing(:friends).depth(2).each {|friend| puts friend[:name]} # # # Find all my friends and include my self in the result # me.outgoing(:friends).depth(4).include_start_node.each {...} # # # Find all my friends friends friends, etc. at any depth # me.outgoing(:friends).depth(:all).each {...} # # # Find all my friends friends but do not include my friends (only depth == 2) # me.outgoing(:friends).depth(2).filter{|path| path.length == 2} # # # Find all my friends but 'cut off' some parts of the traversal path # me.outgoing(:friends).depth(42).prune(|path| an_expression_using_path_returning_true_false } # # # Find all my friends and work colleges # me.outgoing(:friends).outgoing(:work).each {...} # # Of course all the methods outgoing, incoming, both, depth, include_start_node, filter, and prune, eval_paths, unique can be combined. # # See the {Neo4j.rb Guides}[http://neo4j.rubyforge.org/guides/traverser.html] # def outgoing(type) if type Traverser.new(self).outgoing(type) else raise "Not implemented getting all types of outgoing relationship. Specify a relationship type" end end # Returns the incoming nodes of given type(s). # # See #outgoing and http://neo4j.rubyforge.org/guides/traverser.html # def incoming(type) if type Traverser.new(self).incoming(type) else raise "Not implemented getting all types of incoming relationship. Specify a relationship type" end end # Returns both incoming and outgoing nodes of given types(s) # # If a type is not given then it will return all types of relationships. # # See #outgoing and http://neo4j.rubyforge.org/guides/traverser.html # def both(type=nil) if type Traverser.new(self).both(type) else Traverser.new(self) # default is both end end # Traverse using a block. The block is expected to return one of the following values: # * :exclude_and_continue # * :exclude_and_prune # * :include_and_continue # * :include_and_prune # This value decides if it should continue to traverse and if it should include the node in the traversal result. # The block will receive a path argument. # # ==== Example # # @pet0.eval_paths {|path| path.end_node == @principal1 ? :include_and_prune : :exclude_and_continue }.unique(:node_path).depth(:all) # # ==== See also # # * How to use - http://neo4j.rubyforge.org/guides/traverser.html # * the path parameter - http://api.neo4j.org/1.4/org/neo4j/graphdb/Path.html # * the #unique method - if paths should be visit more the once, etc... # def eval_paths(&eval_block) Traverser.new(self).eval_paths(&eval_block) end # Sets uniqueness of nodes or relationships to visit during a traversals. # # Allowed values # * :node_global A node cannot be traversed more than once (default) # * :node_path For each returned node there 's a unique path from the start node to it. # * :node_recent This is like :node_global, but only guarantees uniqueness among the most recent visited nodes, with a configurable count. # * :none No restriction (the user will have to manage it). # * :rel_global A relationship cannot be traversed more than once, whereas nodes can. # * :rel_path :: No restriction (the user will have to manage it). # * :rel_recent Same as for :node_recent, but for relationships. # # See example in #eval_paths # See http://api.neo4j.org/1.4/org/neo4j/kernel/Uniqueness.html and http://neo4j.rubyforge.org/guides/traverser.html def unique(u) Traverser.new(self).unique(u) end end end