Sorry to beat on this old horse again, but I just thought I'd share another solution: using the graph matching component (in Java, but you could probably translate it quite easily to Scala):
public class VisibleMessagesByFollowedUsers implements Iterable<Node> { private final PatternNode start = new PatternNode(); private final PatternNode message = new PatternNode(); private final Node startNode; public VisibleMessagesByFollowedUsers( Node startNode ) { this.startNode = startNode; if ( !STATIC_PATTERN ) start.setAssociation( startNode ); PatternNode user = new PatternNode(); start.createRelationshipTo( user, withName( "FOLLOWS" ) ); user.createRelationshipTo( message, withName( "CREATED" ) ); message.createRelationshipTo( start, withName( "IS_VISIBLE_BY" ) ); } public Iterator<Node> iterator() { Iterable<PatternMatch> matches = PatternMatcher.getMatcher().match( start, startNode ); return new IteratorWrapper<Node, PatternMatch>( matches.iterator() ) { @Override protected Node underlyingObjectToObject( PatternMatch match ) { return match.getNodeFor( message ); } }; } } This code would then be used like so: for ( Node message : new VisibleMessagesByFollowedUsers( userNodeToGetMessagesFor ) ) { displayMessageToUser( message ); } Happy Hacking! - Tobias On Wed, Mar 17, 2010 at 12:06 PM, Craig Taverner <cr...@amanzi.com> wrote: > I'm uncertain about one ambiguity in your model, you are able to find > messages through FOLLOWS and IS_VISIBLE_BY. These will give two different > sets, and my first impression was that FOLLOWS gives you the right answer. > In other words you want to query for 'all messages by users I follow'? In > that case you do not need IS_VISIBLE_BY. However, if there are messages by > people you follow, but are not allowed to see, then you also need the > IS_VISIBLE_BY. But I would still reconsider linking directly from the > viewer > to the message for that case. I'd rather have the messages linked to some > categorization structure for things like 'public', 'private', etc. > > Anyway, here are some suggestions for the various approaches above: > *'all messages by users I follow'* > val msgs = viewer.traverse( > Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, > (tp: TraversalPosition) => IsMessage(tp.currentNode()), > Rels.FOLLOWS, Direction.OUTGOING, > Rels.CREATED, Direction.OUTGOING) > > *'all messages visible to me'* > val msgs = viewer.traverse( > Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, > ReturnableEvaluator.ALL_BUT_START_NODE, > Rels.IS_VISIBLE_BY, Direction.INCOMING) > > *'all messages, visible to me, by people I follow'* > val msgs = viewer.traverse( > Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, > (tp: TraversalPosition) => { > val msg = tp.currentNode() > IsMessage(msg) && IsVisibleBy(msg,viewer) > }, > Rels.FOLLOWS, Direction.OUTGOING, > Rels.CREATED, Direction.OUTGOING) > > Of course I assume you make the utility functions IsMessage(node: Node) and > IsVisibleBy(msg: Node, user: Node), and these will test the existance of > properties and relations as appropriate to make the decision. > > > On Wed, Mar 17, 2010 at 6:32 AM, Lincoln <linxbet...@gmail.com> wrote: > > > Hi, I've just started looking at Neo4j and I'm quite intrigued. However, > > the cognitive dissonance that I've grown so used to in modeling storage > is > > proving to be a bit difficult to let go at this early stage :) > > > > I was hoping that if someone could help me through an example I would be > > able to grok how to properly structure my data and query it in Neo4j. > > > > Nodes: > > Message( text: String ) > > User( id: Long ) > > > > Relationships: > > CREATED > > FOLLOWS > > IS_VISIBLE_BY > > > > So I might have a graph with entries like so: > > > > User(1) --> CREATED --> Message("i woke up late today") > > User(2) --> CREATED --> Message("hello") > > User(3) --> CREATED --> Message("ugh, i hate mondays") > > > > User(1) --> FOLLOWS --> User(2) > > > > Let's also say all messages are visible to User 1. > > > > Message("i woke up late today") --> IS_VISIBLE_BY --> User(1) > > Message("hello") --> IS_VISIBLE_BY --> User(1) > > Message("ugh, i hate mondays") --> IS_VISIBLE_BY --> User(1) > > > > So, I can do a simple traversal for visible: > > > > val graphDb = new EmbeddedGraphDatabase( "path/to/neo4j-db" ) > > val index = new LuceneIndexService( graphDb ) > > val viewer = index.getSingleNode("id", 1) > > val msgs = viewer.traverse( Order.BREADTH_FIRST, > > StopEvaluator.END_OF_GRAPH, > > ReturnableEvaluator.ALL_BUT_START_NODE, Rels.IS_VISIBLE_BY, > > Direction.INCOMING) > > msgs.toList.map(_.toJson).mkString("{ msgs : [", ",", "] }") // assuming > i > > have the relevant functions > > > > But let's say that this is going to return too many messages. Just > because > > all the messages are possibly visible to me, doesn't mean I want to see > > them > > all. So, I'd like to additionally filter by the FOLLOWS relationship. > I'd > > like to express "get all messages that are visible and were created by a > > user that I follow." Can someone show me an example of how to do that? > > > > I'm guessing that you need to implement a custom ReturnableEvaluator, but > I > > don't understand how you traverse multiple relationships at the same > time. > > > > Thanks, > > Lincoln > > _______________________________________________ > > Neo mailing list > > User@lists.neo4j.org > > https://lists.neo4j.org/mailman/listinfo/user > > > _______________________________________________ > Neo 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 _______________________________________________ Neo mailing list User@lists.neo4j.org https://lists.neo4j.org/mailman/listinfo/user