Hi Neo4j enthusiasts!

Yesterday I committed an API that Mattias and I have been working on for a
few days. It comes in the form of two new interfaces Expander and Expansion
(in the org.neo4j.graphdb package), and four new methods in the Node
interface (method names starting with "expand").

The two main problems this API solves are:
1. Adds a clean way for getting related nodes from a source node.
2. Adds a type safe way for declaratively specifying any combination of
RelationshipTypes and Directions to expand.

This replaces what was actually an anti-pattern, but something we saw people
doing a lot: using a depth-one traversal to get the nodes related to a node,
without needing to bother with the Relationship interface. Example:

// The most convenient way to write it in the past:
Node source = ...
Traverser traverser = source.traverse(
    Traverser.Order.DEPTH_FIRST,
    new StopAtDepth( 1 ),
    ReturnableEvaluator.ALL_BUT_START_NODE,
    TYPE_ONE, Direction.INCOMING,
    TYPE_TWO, Direction.OUTGOING);
for (Node related : traverser) {
    doSomethingWith( related );
}

// The previously recommended (and bloated) way of doing it:
Node source = ...
for (Relationship rel : source.getRelationships( TYPE_ONE, TYPE_TWO )) {
    Node related;
    if (rel.isType(TYPE_ONE)) {
        related = rel.getStartNode();
        if (related.equals(source)) continue; // we only want INCOMING
TYPE_ONE
    } else if (rel.isType(TYPE_TWO)) {
        related = rel.getEndNode();
        if (related.equals(source)) continue; // we only want OUTGOING
TYPE_TWO
    } else {
        continue; // should never happen, but makes javac know that related
is != null
    }
    doSomethingWith( related );
}

// With the new API:
Node source = ...
for (Node related : source.expand( TYPE_ONE, Direction.INCOMING )
                          .add( TYPE_TWO, Direction.OUTGOING ).nodes()) {
    doSomethingWith( related );
}

The return type of the Node.expand(...)-methods are the new Expansion type,
it defaults to expanding to Relationship, but the Expansion.nodes()-method
makes it expand to Node. It also contains the add()-methods seen above for
specifying RelationshipTypes to include in the expansion. The spelling of
this method isn't perfectly decided yet, we are choosing between "add",
"and" and "include", we want something that reads nicely in the code, but
doesn't conflict with keywords in other JVM-languages ("and" is a keyword in
Python, and I think "include" means something special in Ruby). There is
also an Expansion.exlude(RelationshipType)-method for use together with the
Node.expandAll().

The Expansion is backed by the newly added companion interface Expander.
This is an extension of RelationshipExpander that adds builder capabilities.
It turns the functionality of the DefultExpander implementation class (now
removed) into an interface in the API. RelationshipExpander is still around
as a single method interface, which is useful for when you want to implement
your own expansion logic.

This API is added to trunk so that we can get feedback from everyone who use
the snapshot builds of Neo4j, if the response to this API isn't positive, it
will probably be removed before the release of 1.1, so please submit
comments in this thread on what you think about this API.

Happy Hacking,
-- 
Tobias Ivarsson <tobias.ivars...@neotechnology.com>
Hacker, Neo Technology
www.neotechnology.com
Cellphone: +46 706 534857
_______________________________________________
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user

Reply via email to