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

Reply via email to