[Neo4j] Cypher - variable length relationships that *aren't* of a type

660 views
Skip to first unread message

Matt Luongo

unread,
Dec 8, 2011, 6:12:26 PM12/8/11
to Neo4j user discussions
Hey everybody,

I'm trying to write a query that returns a small subgraph around a type
system's sub-reference node, excluding relationships used to
define the in-graph type hierarchy.

Eg, given a graph

(0)-[:TYPE]->(1)-[:INSTANCE]->(2)-[:SOMETYPE1]->(3)
(2)-[:SOMETYPE2]->(4)-[:SOMETYPE5]->(5)-[:SOMETYPE6]->(6)
(7)-[:SOMETYPE7]->(2)

I'd like to get all paths from length 0 to 5 from node (2), excluding those
that start with the 'INSTANCE' relationship type.

I started with

`START a = node(2) MATCH p = (a -[g*0..5]->b) WHERE not(type(g) =
"INSTANCE") RETURN p`, which doesn't seem to be valid.
Then I realized that even if it were, this statement would still traverse
across the reference node (potentially hitting supernodes in the
type hierarchy) because where clauses are evaluated after traversals.

Is there a way to accomplish what I need in the match clause? Basically,
some way to say "any relationship but these types, path length 0-5".

Thanks!

--
Matt Luongo
Co-Founder, Scholr.ly
_______________________________________________
NOTICE: THIS MAILING LIST IS BEING SWITCHED TO GOOGLE GROUPS, please register and consider posting at https://groups.google.com/forum/#!forum/neo4j

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

Andres Taylor

unread,
Dec 8, 2011, 6:54:36 PM12/8/11
to Neo4j user discussions
On Fri, Dec 9, 2011 at 12:12 AM, Matt Luongo <ma...@scholr.ly> wrote:

> Hey everybody,
>
> I'm trying to write a query that returns a small subgraph around a type
> system's sub-reference node, excluding relationships used to
> define the in-graph type hierarchy.
>
> Eg, given a graph
>
> (0)-[:TYPE]->(1)-[:INSTANCE]->(2)-[:SOMETYPE1]->(3)
> (2)-[:SOMETYPE2]->(4)-[:SOMETYPE5]->(5)-[:SOMETYPE6]->(6)
> (7)-[:SOMETYPE7]->(2)
>
> I'd like to get all paths from length 0 to 5 from node (2), excluding those
> that start with the 'INSTANCE' relationship type.
>
> I started with
>
> `START a = node(2) MATCH p = (a -[g*0..5]->b) WHERE not(type(g) =
> "INSTANCE") RETURN p`, which doesn't seem to be valid.
>

You are not the first one to run into this. "g" is an iterable of
relationships, and not a single relationship. Maybe we should make this a
valid query...

Anyway, with Cypher as it works today, you have to do this:


START a = node(2)
MATCH p = (a -[g*0..5]->b)

WHERE ALL(r in g WHERE not(type(r) ="INSTANCE")
RETURN p

Thinking about this, it would be trivial to translate your query to this
query under the hood. WDYT?

Then I realized that even if it were, this statement would still traverse
> across the reference node (potentially hitting supernodes in the
> type hierarchy) because where clauses are evaluated after traversals.
>

No, the pattern matcher evaluates predicates as soon as the necessary parts
have been found, with a few exceptions. Filtering after the fact would be
much more expensive. I think the very first version of Cypher did do this,
but it's been changed for quite some time now.

Andrés

Matt Luongo

unread,
Dec 8, 2011, 10:53:59 PM12/8/11
to Neo4j user discussions
Andrés,

You are not the first one to run into this. "g" is an iterable of
> relationships, and not a single relationship. Maybe we should make this a
> valid query...
>
> Anyway, with Cypher as it works today, you have to do this:
> START a = node(2)
> MATCH p = (a -[g*0..5]->b)
> WHERE ALL(r in g WHERE not(type(r) ="INSTANCE")
> RETURN p
>
> Thinking about this, it would be trivial to translate your query to this
> query under the hood. WDYT?


Thanks for the quick response! My only concern about translating the query
is that it could prevent moments like this- if the query had "just worked"
I would have continued to misunderstand 'g' as a collection. Maybe a few
function aliases, like `ALL_OF_TYPE(g, 'INSTANCE')`, `NONE_OF_TYPE(g,
'INSTANCE')`, etc would make sense? They serve the same purpose, are easily
discoverable in docs, and make it really clear that multi-hop
relation identifiers refer to collections.


>

Then I realized that even if it were, this statement would still traverse
> > across the reference node (potentially hitting supernodes in the
> > type hierarchy) because where clauses are evaluated after traversals.
> >
>
> No, the pattern matcher evaluates predicates as soon as the necessary parts
> have been found, with a few exceptions. Filtering after the fact would be
> much more expensive. I think the very first version of Cypher did do this,
> but it's been changed for quite some time now.


Ah! I saw some mention of subgraph generation and filtering being separate.
I thought that was pretty dumb, but with all the talk about Cypher's
mediocre performance I was worried it was true.

Thanks for educating me!

--
Matt Luongo
Co-Founder, Scholr.ly

Reply all
Reply to author
Forward
0 new messages