Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-24 Thread Atle Prange
I agree, lets keep it immutable, then its safe to keep the expander around.


Two suggestions:
Your could provide a reusable expander:

Expander e = Expanders.outgoing().along(FRIEND).and(ENEMY);

for(Node n:e.expand(node)){
...
}

or a onetime expander:

for(Node n : node.expand().outgoing().along(FRIEND).and(ENEMY)){
...
}

OR

for(Node n : node.expand().outgoing().include(FRIEND).include(ENEMY)){
...
}

OR

for(Node n : node.expand().outgoing().with(FRIEND).with(ENEMY)){
...
}

-atle
___
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user


Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-24 Thread Craig Taverner
I guess I would have just added a clear() method to the expansion. But of
course I understand that using mutable expansions requires that the user
actually understand the implications, which goes against the simplicity of
the DSL.

On Thu, Jun 24, 2010 at 12:23 AM, Tobias Ivarsson 
tobias.ivars...@neotechnology.com wrote:

 The problem with the code below is that once you've used the
 Person.getFriends(minAge)-method once, the friends-expansion will have that
 filter added to it forever (if it's mutable), and that means that you will
 never be able to get the younger friends of that person.

 However, reusing an expansion might be so uncommon that it's not even worth
 bothering with. But if so, it will almost always be used fluent-style,
 and
 the use case for being able to mutate it disappears. Ergo, let's keep it
 immutable, since it enables more use cases.

 -t

 On Wed, Jun 23, 2010 at 8:47 PM, Craig Taverner cr...@amanzi.com wrote:

  Mutable objects have their issues, and yet this is a common and popular
  paradigm in DSL design. I guess however the point with a DSL is that it
 is
  so simple and limited that it compensates for the potential risks.
 Similar
  to the dynamic versus static language argument.
 
  Now there are ways to reduce the risk. If I remember correctly, one
 pattern
  commonly used in the DSL book was to remain strict with model objects,
 but
  slack on model builder objects. In this case the Node and Person objects
  are
  model objects, and we would put the fancy DSL stuff into a separate
 class,
  not as a static method of the Person class. This can help conceptually
  separate the solid and reliable model from the convenient DSL.
 
  On a separate note, perhaps I'm just being slow, but I don't see the
  aspects
  of the code below that would be disabled by a mutable builder? Is it the
  final on 'friends'? That keyword should not stop modifying the contents
 of
  friends. ANd you code below does not expose the friends instance to
 outside
  influences, so no-one can modify it anyway. What am I missing.
 
  On Wed, Jun 23, 2010 at 8:15 PM, Tobias Ivarsson 
  tobias.ivars...@neotechnology.com wrote:
 
   Because mutable objects are evil. It would for example make it
 impossible
   to
   write classes like this:
  
   class Person {
  private final ExpansionNode friends;
  Person(Node node) {
  this.friends = node.expand( FRIEND ).nodes();
  }
  IterablePerson getFriends() {
  return persons( friends );
  }
  IterablePerson getFriends( final int minimumAge ) {
  return persons( friends.filterNodes( new PredicateNode() {
  public boolean accept(Node friend) {
  return minimumAge = (Integer)friend.getProperty(age);
  }
  }) );
  }
  static IterablePerson persons( IterableNode persons ) {
  return IterableWrapperPerson, Node( persons ) {
  protected Person underlyingObjectToObject( Node person ) {
  return new Person( person );
  }
  }
  }
   }
  
   This might be an acceptable loss though. This could be a case where it
 is
   ok
   to reuse the same object and mutate the internal state. It's something
 to
   think about...
  
   -tobias
  
   On Wed, Jun 23, 2010 at 7:10 PM, Craig Taverner cr...@amanzi.com
  wrote:
  
Why not have includes() return the same instance with internal state
changed, then the various call options are equivalent.
   
On Jun 23, 2010 6:41 PM, Tobias Ivarsson 
tobias.ivars...@neotechnology.com wrote:
   
On Wed, Jun 23, 2010 at 6:10 PM, Craig Taverner cr...@amanzi.com
   wrote:

 (I also noticed that r...
I get that feeling as well. Another feeling I get with includes() is
  that
it
might be possible to do the following:
   
   
ExpansionRelationship expansion = startNode.expand( KNOWS );
expansion.includes( LIKES );
expansion.includes( LOVES );
for (Node node : expansion.nodes()) {
  ...
}
   
With includes() one gets the feeling that the above would expand
 LOVES,
LIKES and KNOWS relationships, but it will in fact only expand KNOWS
relationships. With and() I don't think that mistake would be as
  common.
   
Cheers,
--
   
Tobias Ivarsson tobias.ivars...@neotechnology.com
Hacker, Neo Technology
www.neotechnology.com
Cel...
___
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user
   
  
  
  
   --
   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
  
  ___
  Neo4j mailing list
  User@lists.neo4j.org
  

Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Alex Averbuch
Hi Tobias,
It seems as though the new changes have broken the AStar code I'm using.

I use:
neo4j-apoc 1.1-SNAPSHOT
neo4j-graph-algo 0.5-SNAPSHOT

AStar uses DefaultExpander and can no longer find it.

Here's an example of the code that worked until now.

DefaultExpander relExpander = new DefaultExpander();
relExpander.add(GISRelationshipTypes.BICYCLE_WAY, Direction.BOTH);
AStar sp = new AStar(graphDb, relExpander, costEval, estimateEval);
Path path = sp.findSinglePath(startNode, endNode);

The problem seems to be that AStar wants a RelationshipExpander but now I
can only create an ExpansionRelationship.

Do you have any suggestions as to how to make this work again?

Regards,
Alex


On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson 
tobias.ivars...@neotechnology.com wrote:

 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

___
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user


Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Anders Nawroth
Hi!

See:
http://www.mail-archive.com/user@lists.neo4j.org/msg04044.html

/anders

On 06/23/2010 03:44 PM, Alex Averbuch wrote:
 Hi Tobias,
 It seems as though the new changes have broken the AStar code I'm using.

 I use:
 neo4j-apoc 1.1-SNAPSHOT
 neo4j-graph-algo 0.5-SNAPSHOT

 AStar uses DefaultExpander and can no longer find it.

 Here's an example of the code that worked until now.

 DefaultExpander relExpander = new DefaultExpander();
 relExpander.add(GISRelationshipTypes.BICYCLE_WAY, Direction.BOTH);
 AStar sp = new AStar(graphDb, relExpander, costEval, estimateEval);
 Path path = sp.findSinglePath(startNode, endNode);

 The problem seems to be that AStar wants a RelationshipExpander but now I
 can only create an ExpansionRelationship.

 Do you have any suggestions as to how to make this work again?

 Regards,
 Alex


 On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson
 tobias.ivars...@neotechnology.com  wrote:

 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 Ivarssontobias.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

 ___
 Neo4j mailing list
 User@lists.neo4j.org
 https://lists.neo4j.org/mailman/listinfo/user
___
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user


Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Mattias Persson
Also, the latest graph-algo is 0.6-SNAPSHOT... so use that instead

2010/6/23 Anders Nawroth and...@neotechnology.com

 Hi!

 See:
 http://www.mail-archive.com/user@lists.neo4j.org/msg04044.html

 /anders

 On 06/23/2010 03:44 PM, Alex Averbuch wrote:
  Hi Tobias,
  It seems as though the new changes have broken the AStar code I'm using.
 
  I use:
  neo4j-apoc 1.1-SNAPSHOT
  neo4j-graph-algo 0.5-SNAPSHOT
 
  AStar uses DefaultExpander and can no longer find it.
 
  Here's an example of the code that worked until now.
 
  DefaultExpander relExpander = new DefaultExpander();
  relExpander.add(GISRelationshipTypes.BICYCLE_WAY, Direction.BOTH);
  AStar sp = new AStar(graphDb, relExpander, costEval, estimateEval);
  Path path = sp.findSinglePath(startNode, endNode);
 
  The problem seems to be that AStar wants a RelationshipExpander but now I
  can only create an ExpansionRelationship.
 
  Do you have any suggestions as to how to make this work again?
 
  Regards,
  Alex
 
 
  On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson
  tobias.ivars...@neotechnology.com  wrote:
 
  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 Ivarssontobias.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
 
  ___
  Neo4j mailing list
  User@lists.neo4j.org
  https://lists.neo4j.org/mailman/listinfo/user
 

Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Alex Averbuch
Hi guys,
thanks!

I've pulled the latest java-astar-routing and looking at it now.
Have changed to SNAPSHOT 0.6 too.

Has the AStar algorithm been changed to use the Traversal framework now?
If so, is there any way I can use the old AStar version?

The last one required neo4j-apoc 1.1-SNAPSHOT  neo4j-graph-algo
0.5-SNAPSHOT, but no longer works with these.
Is there any combination of neo4j-graph-algo and neo4j-apoc that will work
with the old version of AStar?

My problem is this...
We are in the final stages of evaluation for our thesis and have been asked
if we can run a bunch of extra experiments.
We use AStar on the GIS dataset experiments.
We do NOT want to use the Traversal framework at all as the way we log
traffic is by listening to the Add, Remove, Delete, Get, etc methods of
GraphDatabaseService.
The Traversal framework goes around these as far as I know, so we would lose
our ability to monitor.

Any suggestions would be great!

Thanks,
Alex


On Wed, Jun 23, 2010 at 3:52 PM, Mattias Persson
matt...@neotechnology.comwrote:

 Also, the latest graph-algo is 0.6-SNAPSHOT... so use that instead

 2010/6/23 Anders Nawroth and...@neotechnology.com

  Hi!
 
  See:
  http://www.mail-archive.com/user@lists.neo4j.org/msg04044.html
 
  /anders
 
  On 06/23/2010 03:44 PM, Alex Averbuch wrote:
   Hi Tobias,
   It seems as though the new changes have broken the AStar code I'm
 using.
  
   I use:
   neo4j-apoc 1.1-SNAPSHOT
   neo4j-graph-algo 0.5-SNAPSHOT
  
   AStar uses DefaultExpander and can no longer find it.
  
   Here's an example of the code that worked until now.
  
   DefaultExpander relExpander = new DefaultExpander();
   relExpander.add(GISRelationshipTypes.BICYCLE_WAY, Direction.BOTH);
   AStar sp = new AStar(graphDb, relExpander, costEval, estimateEval);
   Path path = sp.findSinglePath(startNode, endNode);
  
   The problem seems to be that AStar wants a RelationshipExpander but now
 I
   can only create an ExpansionRelationship.
  
   Do you have any suggestions as to how to make this work again?
  
   Regards,
   Alex
  
  
   On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson
   tobias.ivars...@neotechnology.com  wrote:
  
   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().
  

Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Mattias Persson
It works with graph-algo 0.6-SNAPSHOT and there's an AStar.java (which is
the old version) and one ExperimentalAStar.java which uses the new
traversal framework.

2010/6/23 Alex Averbuch alex.averb...@gmail.com

 Hi guys,
 thanks!

 I've pulled the latest java-astar-routing and looking at it now.
 Have changed to SNAPSHOT 0.6 too.

 Has the AStar algorithm been changed to use the Traversal framework now?
 If so, is there any way I can use the old AStar version?

 The last one required neo4j-apoc 1.1-SNAPSHOT  neo4j-graph-algo
 0.5-SNAPSHOT, but no longer works with these.
 Is there any combination of neo4j-graph-algo and neo4j-apoc that will work
 with the old version of AStar?

 My problem is this...
 We are in the final stages of evaluation for our thesis and have been asked
 if we can run a bunch of extra experiments.
 We use AStar on the GIS dataset experiments.
 We do NOT want to use the Traversal framework at all as the way we log
 traffic is by listening to the Add, Remove, Delete, Get, etc methods of
 GraphDatabaseService.
 The Traversal framework goes around these as far as I know, so we would
 lose
 our ability to monitor.

 Any suggestions would be great!

 Thanks,
 Alex


 On Wed, Jun 23, 2010 at 3:52 PM, Mattias Persson
 matt...@neotechnology.comwrote:

  Also, the latest graph-algo is 0.6-SNAPSHOT... so use that instead
 
  2010/6/23 Anders Nawroth and...@neotechnology.com
 
   Hi!
  
   See:
   http://www.mail-archive.com/user@lists.neo4j.org/msg04044.html
  
   /anders
  
   On 06/23/2010 03:44 PM, Alex Averbuch wrote:
Hi Tobias,
It seems as though the new changes have broken the AStar code I'm
  using.
   
I use:
neo4j-apoc 1.1-SNAPSHOT
neo4j-graph-algo 0.5-SNAPSHOT
   
AStar uses DefaultExpander and can no longer find it.
   
Here's an example of the code that worked until now.
   
DefaultExpander relExpander = new DefaultExpander();
relExpander.add(GISRelationshipTypes.BICYCLE_WAY, Direction.BOTH);
AStar sp = new AStar(graphDb, relExpander, costEval, estimateEval);
Path path = sp.findSinglePath(startNode, endNode);
   
The problem seems to be that AStar wants a RelationshipExpander but
 now
  I
can only create an ExpansionRelationship.
   
Do you have any suggestions as to how to make this work again?
   
Regards,
Alex
   
   
On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson
tobias.ivars...@neotechnology.com  wrote:
   
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 

Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Alex Averbuch
Sweet,
Experiments are running fine again.

Thanks for the quick help!
Alex

On Wed, Jun 23, 2010 at 4:17 PM, Mattias Persson
matt...@neotechnology.comwrote:

 It works with graph-algo 0.6-SNAPSHOT and there's an AStar.java (which is
 the old version) and one ExperimentalAStar.java which uses the new
 traversal framework.

 2010/6/23 Alex Averbuch alex.averb...@gmail.com

  Hi guys,
  thanks!
 
  I've pulled the latest java-astar-routing and looking at it now.
  Have changed to SNAPSHOT 0.6 too.
 
  Has the AStar algorithm been changed to use the Traversal framework now?
  If so, is there any way I can use the old AStar version?
 
  The last one required neo4j-apoc 1.1-SNAPSHOT  neo4j-graph-algo
  0.5-SNAPSHOT, but no longer works with these.
  Is there any combination of neo4j-graph-algo and neo4j-apoc that will
 work
  with the old version of AStar?
 
  My problem is this...
  We are in the final stages of evaluation for our thesis and have been
 asked
  if we can run a bunch of extra experiments.
  We use AStar on the GIS dataset experiments.
  We do NOT want to use the Traversal framework at all as the way we log
  traffic is by listening to the Add, Remove, Delete, Get, etc methods
 of
  GraphDatabaseService.
  The Traversal framework goes around these as far as I know, so we would
  lose
  our ability to monitor.
 
  Any suggestions would be great!
 
  Thanks,
  Alex
 
 
  On Wed, Jun 23, 2010 at 3:52 PM, Mattias Persson
  matt...@neotechnology.comwrote:
 
   Also, the latest graph-algo is 0.6-SNAPSHOT... so use that instead
  
   2010/6/23 Anders Nawroth and...@neotechnology.com
  
Hi!
   
See:
http://www.mail-archive.com/user@lists.neo4j.org/msg04044.html
   
/anders
   
On 06/23/2010 03:44 PM, Alex Averbuch wrote:
 Hi Tobias,
 It seems as though the new changes have broken the AStar code I'm
   using.

 I use:
 neo4j-apoc 1.1-SNAPSHOT
 neo4j-graph-algo 0.5-SNAPSHOT

 AStar uses DefaultExpander and can no longer find it.

 Here's an example of the code that worked until now.

 DefaultExpander relExpander = new DefaultExpander();
 relExpander.add(GISRelationshipTypes.BICYCLE_WAY, Direction.BOTH);
 AStar sp = new AStar(graphDb, relExpander, costEval, estimateEval);
 Path path = sp.findSinglePath(startNode, endNode);

 The problem seems to be that AStar wants a RelationshipExpander but
  now
   I
 can only create an ExpansionRelationship.

 Do you have any suggestions as to how to make this work again?

 Regards,
 Alex


 On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson
 tobias.ivars...@neotechnology.com  wrote:

 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

Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Tobias Ivarsson
Did anyone have an opinion on what to call the methods on the Expansion
interface that specify which types to expand.

Alternative 1)
ExpansionT and( RelationshipType type );
ExpansionT and( RelationshipType type, Direction direction );
ExpansionT not( RelationshipType type );

Examples:
for (Node node : startNode.expand( KNOWS )
  .and( LIKES )
  .and( LOVES ) ) {
   doSomethingWith(node);
}

ExpansionRelationship expansion = startNode.expand( KNOWS );
expansion = expansion.and( LIKES );
expansion = expansion.and( LOVES );


Alternative 2)
ExpansionT including( RelationshipType type );
ExpansionT including( RelationshipType type, Direction direction );
ExpansionT excluding( RelationshipType type );

Examples:
for (Node node : startNode.expand( KNOWS )
  .including( LIKES )
  .including( LOVES ) ) {
   doSomethingWith(node);
}

ExpansionRelationship expansion = startNode.expand( KNOWS );
expansion = expansion.including( LIKES );
expansion = expansion.including( LOVES );


Cheers,
Tobias

On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson 
tobias.ivars...@neotechnology.com wrote:

 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




-- 
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


Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Alex Averbuch
Hi,
Personally I'd prefer and/not.
It's intuitive to any programmer and has the bonus of being much shorter, so
long complex expansions will appear less messy in practice.

On Wed, Jun 23, 2010 at 5:45 PM, Tobias Ivarsson 
tobias.ivars...@neotechnology.com wrote:

 Did anyone have an opinion on what to call the methods on the Expansion
 interface that specify which types to expand.

 Alternative 1)
 ExpansionT and( RelationshipType type );
 ExpansionT and( RelationshipType type, Direction direction );
 ExpansionT not( RelationshipType type );

 Examples:
 for (Node node : startNode.expand( KNOWS )
  .and( LIKES )
  .and( LOVES ) ) {
   doSomethingWith(node);
 }

 ExpansionRelationship expansion = startNode.expand( KNOWS );
 expansion = expansion.and( LIKES );
 expansion = expansion.and( LOVES );


 Alternative 2)
 ExpansionT including( RelationshipType type );
 ExpansionT including( RelationshipType type, Direction direction );
 ExpansionT excluding( RelationshipType type );

 Examples:
 for (Node node : startNode.expand( KNOWS )
  .including( LIKES )
  .including( LOVES ) ) {
   doSomethingWith(node);
 }

 ExpansionRelationship expansion = startNode.expand( KNOWS );
 expansion = expansion.including( LIKES );
 expansion = expansion.including( LOVES );


 Cheers,
 Tobias

 On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson 
 tobias.ivars...@neotechnology.com wrote:

  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 

Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Craig Taverner
I like this new API. It is a tiny first step towards making the Java API a
little more DSL-like (1% of the way to the current scala and ruby API's :-)

My vote is actually for the includes() approach only because *and* is such a
widely used keyword. However, a quick test in Ruby showed that while
include() and 'and' are used, they can be overridden, and I believe using
either in the Java API will not affect their use in the Ruby API.

But to be careful, I'd still lean towards the safer includes() option.

And, this is Java, after all. Verbosity is expected ;-)

(I also noticed that reading the examples with and() correctly indicates
that the order of definition is irrelevant, while includes() almost implies
that the first relationship type has some kind of precedence. Could it?)

On Wed, Jun 23, 2010 at 6:01 PM, Alex Averbuch alex.averb...@gmail.comwrote:

 Hi,
 Personally I'd prefer and/not.
 It's intuitive to any programmer and has the bonus of being much shorter,
 so
 long complex expansions will appear less messy in practice.

 On Wed, Jun 23, 2010 at 5:45 PM, Tobias Ivarsson 
 tobias.ivars...@neotechnology.com wrote:

  Did anyone have an opinion on what to call the methods on the Expansion
  interface that specify which types to expand.
 
  Alternative 1)
  ExpansionT and( RelationshipType type );
  ExpansionT and( RelationshipType type, Direction direction );
  ExpansionT not( RelationshipType type );
 
  Examples:
  for (Node node : startNode.expand( KNOWS )
   .and( LIKES )
   .and( LOVES ) ) {
doSomethingWith(node);
  }
 
  ExpansionRelationship expansion = startNode.expand( KNOWS );
  expansion = expansion.and( LIKES );
  expansion = expansion.and( LOVES );
 
 
  Alternative 2)
  ExpansionT including( RelationshipType type );
  ExpansionT including( RelationshipType type, Direction direction );
  ExpansionT excluding( RelationshipType type );
 
  Examples:
  for (Node node : startNode.expand( KNOWS )
   .including( LIKES )
   .including( LOVES ) ) {
doSomethingWith(node);
  }
 
  ExpansionRelationship expansion = startNode.expand( KNOWS );
  expansion = expansion.including( LIKES );
  expansion = expansion.including( LOVES );
 
 
  Cheers,
  Tobias
 
  On Wed, Jun 23, 2010 at 11:14 AM, Tobias Ivarsson 
  tobias.ivars...@neotechnology.com wrote:
 
   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 

Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Tobias Ivarsson
On Wed, Jun 23, 2010 at 6:10 PM, Craig Taverner cr...@amanzi.com wrote:

 (I also noticed that reading the examples with and() correctly indicates
 that the order of definition is irrelevant, while includes() almost implies
 that the first relationship type has some kind of precedence. Could it?)


I get that feeling as well. Another feeling I get with includes() is that it
might be possible to do the following:

ExpansionRelationship expansion = startNode.expand( KNOWS );
expansion.includes( LIKES );
expansion.includes( LOVES );
for (Node node : expansion.nodes()) {
...
}

With includes() one gets the feeling that the above would expand LOVES,
LIKES and KNOWS relationships, but it will in fact only expand KNOWS
relationships. With and() I don't think that mistake would be as common.

Cheers,
-- 
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


Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Craig Taverner
Why not have includes() return the same instance with internal state
changed, then the various call options are equivalent.

On Jun 23, 2010 6:41 PM, Tobias Ivarsson 
tobias.ivars...@neotechnology.com wrote:

On Wed, Jun 23, 2010 at 6:10 PM, Craig Taverner cr...@amanzi.com wrote:

 (I also noticed that r...
I get that feeling as well. Another feeling I get with includes() is that it
might be possible to do the following:


ExpansionRelationship expansion = startNode.expand( KNOWS );
expansion.includes( LIKES );
expansion.includes( LOVES );
for (Node node : expansion.nodes()) {
   ...
}

With includes() one gets the feeling that the above would expand LOVES,
LIKES and KNOWS relationships, but it will in fact only expand KNOWS
relationships. With and() I don't think that mistake would be as common.

Cheers,
--

Tobias Ivarsson tobias.ivars...@neotechnology.com
Hacker, Neo Technology
www.neotechnology.com
Cel...
___
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user


Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Tobias Ivarsson
Because mutable objects are evil. It would for example make it impossible to
write classes like this:

class Person {
private final ExpansionNode friends;
Person(Node node) {
this.friends = node.expand( FRIEND ).nodes();
}
IterablePerson getFriends() {
return persons( friends );
}
IterablePerson getFriends( final int minimumAge ) {
return persons( friends.filterNodes( new PredicateNode() {
public boolean accept(Node friend) {
return minimumAge = (Integer)friend.getProperty(age);
}
}) );
}
static IterablePerson persons( IterableNode persons ) {
return IterableWrapperPerson, Node( persons ) {
protected Person underlyingObjectToObject( Node person ) {
return new Person( person );
}
}
}
}

This might be an acceptable loss though. This could be a case where it is ok
to reuse the same object and mutate the internal state. It's something to
think about...

-tobias

On Wed, Jun 23, 2010 at 7:10 PM, Craig Taverner cr...@amanzi.com wrote:

 Why not have includes() return the same instance with internal state
 changed, then the various call options are equivalent.

 On Jun 23, 2010 6:41 PM, Tobias Ivarsson 
 tobias.ivars...@neotechnology.com wrote:

 On Wed, Jun 23, 2010 at 6:10 PM, Craig Taverner cr...@amanzi.com wrote:
 
  (I also noticed that r...
 I get that feeling as well. Another feeling I get with includes() is that
 it
 might be possible to do the following:


 ExpansionRelationship expansion = startNode.expand( KNOWS );
 expansion.includes( LIKES );
 expansion.includes( LOVES );
 for (Node node : expansion.nodes()) {
   ...
 }

 With includes() one gets the feeling that the above would expand LOVES,
 LIKES and KNOWS relationships, but it will in fact only expand KNOWS
 relationships. With and() I don't think that mistake would be as common.

 Cheers,
 --

 Tobias Ivarsson tobias.ivars...@neotechnology.com
 Hacker, Neo Technology
 www.neotechnology.com
 Cel...
 ___
 Neo4j mailing list
 User@lists.neo4j.org
 https://lists.neo4j.org/mailman/listinfo/user




-- 
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


Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Craig Taverner
Mutable objects have their issues, and yet this is a common and popular
paradigm in DSL design. I guess however the point with a DSL is that it is
so simple and limited that it compensates for the potential risks. Similar
to the dynamic versus static language argument.

Now there are ways to reduce the risk. If I remember correctly, one pattern
commonly used in the DSL book was to remain strict with model objects, but
slack on model builder objects. In this case the Node and Person objects are
model objects, and we would put the fancy DSL stuff into a separate class,
not as a static method of the Person class. This can help conceptually
separate the solid and reliable model from the convenient DSL.

On a separate note, perhaps I'm just being slow, but I don't see the aspects
of the code below that would be disabled by a mutable builder? Is it the
final on 'friends'? That keyword should not stop modifying the contents of
friends. ANd you code below does not expose the friends instance to outside
influences, so no-one can modify it anyway. What am I missing.

On Wed, Jun 23, 2010 at 8:15 PM, Tobias Ivarsson 
tobias.ivars...@neotechnology.com wrote:

 Because mutable objects are evil. It would for example make it impossible
 to
 write classes like this:

 class Person {
private final ExpansionNode friends;
Person(Node node) {
this.friends = node.expand( FRIEND ).nodes();
}
IterablePerson getFriends() {
return persons( friends );
}
IterablePerson getFriends( final int minimumAge ) {
return persons( friends.filterNodes( new PredicateNode() {
public boolean accept(Node friend) {
return minimumAge = (Integer)friend.getProperty(age);
}
}) );
}
static IterablePerson persons( IterableNode persons ) {
return IterableWrapperPerson, Node( persons ) {
protected Person underlyingObjectToObject( Node person ) {
return new Person( person );
}
}
}
 }

 This might be an acceptable loss though. This could be a case where it is
 ok
 to reuse the same object and mutate the internal state. It's something to
 think about...

 -tobias

 On Wed, Jun 23, 2010 at 7:10 PM, Craig Taverner cr...@amanzi.com wrote:

  Why not have includes() return the same instance with internal state
  changed, then the various call options are equivalent.
 
  On Jun 23, 2010 6:41 PM, Tobias Ivarsson 
  tobias.ivars...@neotechnology.com wrote:
 
  On Wed, Jun 23, 2010 at 6:10 PM, Craig Taverner cr...@amanzi.com
 wrote:
  
   (I also noticed that r...
  I get that feeling as well. Another feeling I get with includes() is that
  it
  might be possible to do the following:
 
 
  ExpansionRelationship expansion = startNode.expand( KNOWS );
  expansion.includes( LIKES );
  expansion.includes( LOVES );
  for (Node node : expansion.nodes()) {
...
  }
 
  With includes() one gets the feeling that the above would expand LOVES,
  LIKES and KNOWS relationships, but it will in fact only expand KNOWS
  relationships. With and() I don't think that mistake would be as common.
 
  Cheers,
  --
 
  Tobias Ivarsson tobias.ivars...@neotechnology.com
  Hacker, Neo Technology
  www.neotechnology.com
  Cel...
  ___
  Neo4j mailing list
  User@lists.neo4j.org
  https://lists.neo4j.org/mailman/listinfo/user
 



 --
 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

___
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user


Re: [Neo4j] New tentative API in trunk: Expander/Expansion

2010-06-23 Thread Tobias Ivarsson
The problem with the code below is that once you've used the
Person.getFriends(minAge)-method once, the friends-expansion will have that
filter added to it forever (if it's mutable), and that means that you will
never be able to get the younger friends of that person.

However, reusing an expansion might be so uncommon that it's not even worth
bothering with. But if so, it will almost always be used fluent-style, and
the use case for being able to mutate it disappears. Ergo, let's keep it
immutable, since it enables more use cases.

-t

On Wed, Jun 23, 2010 at 8:47 PM, Craig Taverner cr...@amanzi.com wrote:

 Mutable objects have their issues, and yet this is a common and popular
 paradigm in DSL design. I guess however the point with a DSL is that it is
 so simple and limited that it compensates for the potential risks. Similar
 to the dynamic versus static language argument.

 Now there are ways to reduce the risk. If I remember correctly, one pattern
 commonly used in the DSL book was to remain strict with model objects, but
 slack on model builder objects. In this case the Node and Person objects
 are
 model objects, and we would put the fancy DSL stuff into a separate class,
 not as a static method of the Person class. This can help conceptually
 separate the solid and reliable model from the convenient DSL.

 On a separate note, perhaps I'm just being slow, but I don't see the
 aspects
 of the code below that would be disabled by a mutable builder? Is it the
 final on 'friends'? That keyword should not stop modifying the contents of
 friends. ANd you code below does not expose the friends instance to outside
 influences, so no-one can modify it anyway. What am I missing.

 On Wed, Jun 23, 2010 at 8:15 PM, Tobias Ivarsson 
 tobias.ivars...@neotechnology.com wrote:

  Because mutable objects are evil. It would for example make it impossible
  to
  write classes like this:
 
  class Person {
 private final ExpansionNode friends;
 Person(Node node) {
 this.friends = node.expand( FRIEND ).nodes();
 }
 IterablePerson getFriends() {
 return persons( friends );
 }
 IterablePerson getFriends( final int minimumAge ) {
 return persons( friends.filterNodes( new PredicateNode() {
 public boolean accept(Node friend) {
 return minimumAge = (Integer)friend.getProperty(age);
 }
 }) );
 }
 static IterablePerson persons( IterableNode persons ) {
 return IterableWrapperPerson, Node( persons ) {
 protected Person underlyingObjectToObject( Node person ) {
 return new Person( person );
 }
 }
 }
  }
 
  This might be an acceptable loss though. This could be a case where it is
  ok
  to reuse the same object and mutate the internal state. It's something to
  think about...
 
  -tobias
 
  On Wed, Jun 23, 2010 at 7:10 PM, Craig Taverner cr...@amanzi.com
 wrote:
 
   Why not have includes() return the same instance with internal state
   changed, then the various call options are equivalent.
  
   On Jun 23, 2010 6:41 PM, Tobias Ivarsson 
   tobias.ivars...@neotechnology.com wrote:
  
   On Wed, Jun 23, 2010 at 6:10 PM, Craig Taverner cr...@amanzi.com
  wrote:
   
(I also noticed that r...
   I get that feeling as well. Another feeling I get with includes() is
 that
   it
   might be possible to do the following:
  
  
   ExpansionRelationship expansion = startNode.expand( KNOWS );
   expansion.includes( LIKES );
   expansion.includes( LOVES );
   for (Node node : expansion.nodes()) {
 ...
   }
  
   With includes() one gets the feeling that the above would expand LOVES,
   LIKES and KNOWS relationships, but it will in fact only expand KNOWS
   relationships. With and() I don't think that mistake would be as
 common.
  
   Cheers,
   --
  
   Tobias Ivarsson tobias.ivars...@neotechnology.com
   Hacker, Neo Technology
   www.neotechnology.com
   Cel...
   ___
   Neo4j mailing list
   User@lists.neo4j.org
   https://lists.neo4j.org/mailman/listinfo/user
  
 
 
 
  --
  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
 
 ___
 Neo4j mailing list
 User@lists.neo4j.org
 https://lists.neo4j.org/mailman/listinfo/user




-- 
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