Cypher - multiple start points and "complex" matching

908 views
Skip to first unread message

Matt Luongo

unread,
Aug 6, 2012, 1:27:16 PM8/6/12
to ne...@googlegroups.com
Guys,

In neo4django, I used to generate a Cypher query that looked something like this:

    START s0=node(744), s1=node(744) match p0=(s0-[:`chases`]->r0), p1=(s1-[:`chases`]->()-[:`chases`]->r1) RETURN p0, p1

for an example graph looking something like

    Node[744] -[:chases]-> Node[745] -[:chases]-> Node[746]

(or, if you prefer, like this)

I used to get two paths (in some older version...), but now (1.6.3, 1.7.2, 1.8M06) `p0` always returns null, and `p1` returns a proper path. I realize that I could accomplish this with a different syntax (optional relationships?), but the above is really easy to generate. Are the results I'm getting expected, or is this a bug? If not, could someone explain how the semantics have changed? Optional relationships in my use case would be fairly cumbersome.

Thanks!

Wes Freeman

unread,
Aug 6, 2012, 7:06:23 PM8/6/12
to ne...@googlegroups.com
I'm new to neo4j myself, so I'm not sure why those queries no longer work--playing around with that syntax trying to match multiple paths, it seems to sometimes match one path and other times match the other, but I couldn't figure out any rhyme or reason to it, and it never returned both.

Like you said, though, rewriting the query with optional relationships gives you your two paths. It's pretty concise, too--I take it your actual requirements are different than the simple data provided, otherwise this would be a good option: 
START s=node(1) MATCH path=s-[?:chases*1..2]->() RETURN path;

Matt Luongo

unread,
Aug 7, 2012, 9:16:49 AM8/7/12
to ne...@googlegroups.com
Interesting- any Cypher experts want to speak up?

Wes - Re: use case - exactly. In my actual use case there could be 5 other relationship types, and the graph could be more complicated- but I want to pull all of the paths at once.

Michael Hunger

unread,
Aug 7, 2012, 9:33:33 AM8/7/12
to ne...@googlegroups.com
sorry, I think the reason is the identifier uniqueness. 
A node/rel found by a match is only assigned to one identifier, if it is already assigned to r1 it is kind of "used-up" and cannot be assigned again to r0.

You can split the query into two parts like this:

Wes Freeman

unread,
Aug 7, 2012, 9:33:59 AM8/7/12
to ne...@googlegroups.com
You don't have to specify the relationship type with an optional relationship. In a more complicated graph, this might do what you're looking for.

START s=node(1) MATCH path=s-[?*]->() RETURN path;


Wes

Michael Hunger

unread,
Aug 7, 2012, 9:37:13 AM8/7/12
to ne...@googlegroups.com
But you should probably not use optional relationships then, so without the question mark.


START s=node(1) MATCH path=s-[*]->() RETURN path;

Matt Luongo

unread,
Aug 7, 2012, 11:51:29 AM8/7/12
to ne...@googlegroups.com
Michael,

At first, that looked like exactly what I need. However, since I'm using this internally for neo4django, it needs to work for 1.6.3 and 1.7.2 (which don't support "WITH" I believe).

That makes sense- I guess I'll have to keep looking for a solution, or even break the query up :/

Matt Luongo

unread,
Aug 7, 2012, 11:56:29 AM8/7/12
to ne...@googlegroups.com
Right- but I *only* want those 5 rel types returned, not any rel type. This query is part of neo4django's `select_related` function, which basically takes a limited, non-recursive traversal description and executes it as Cypher- thus the strange requirements. Right now it looks like I'll need to run multiple Cypher queries, unless the "WITH" clause gets backported to 1.6 or I come up with some other solution.


On Tuesday, August 7, 2012 9:33:59 AM UTC-4, Wes Freeman wrote:
You don't have to specify the relationship type with an optional relationship. In a more complicated graph, this might do what you're looking for.
START s=node(1) MATCH path=s-[?*]->() RETURN path;


Wes

On Tue, Aug 7, 2012 at 9:16 AM, Matt Luongo wrote:
Interesting- any Cypher experts want to speak up?

Wes - Re: use case - exactly. In my actual use case there could be 5 other relationship types, and the graph could be more complicated- but I want to pull all of the paths at once.

On Monday, August 6, 2012 7:06:23 PM UTC-4, Wes Freeman wrote:
I'm new to neo4j myself, so I'm not sure why those queries no longer work--playing around with that syntax trying to match multiple paths, it seems to sometimes match one path and other times match the other, but I couldn't figure out any rhyme or reason to it, and it never returned both.

Like you said, though, rewriting the query with optional relationships gives you your two paths. It's pretty concise, too--I take it your actual requirements are different than the simple data provided, otherwise this would be a good option: 
START s=node(1) MATCH path=s-[?:chases*1..2]->() RETURN path;

Wes Freeman

unread,
Aug 7, 2012, 12:36:16 PM8/7/12
to ne...@googlegroups.com
Interesting, looking at your code on github it looks like it's a caching mechanism for the models. So, each model has certain relationship types, and you need to match those? The reason you want to match multiple paths at once is to do this for multiple models (if that's the case, do you really have the same starting node for the different models?)?

I'm sure you already know about this, but what about relationship types with pipes, like:
START s=node(1) MATCH path=s-[:KNOWS|LOVES*]->() RETURN path;

http://console.neo4j.org/r/odvhq4

Michael Hunger

unread,
Aug 7, 2012, 12:37:16 PM8/7/12
to ne...@googlegroups.com
What about using the pipe separator for the rel types?

Michael

Sent from mobile device

Matt Luongo

unread,
Aug 7, 2012, 3:42:47 PM8/7/12
to ne...@googlegroups.com
Wes - actually, the same starting *nodes*. Since this works on Django QuerySets, I have a collection of node ids representing models, all of the same type, and use that list to start the query. 

The pipe separator approach will definitely work- I was just hoping to avoid merging the trees in my code and lean on Cypher, like I had been :) Unless I can come up with some other, more easily generated approach, this'll have to do the trick. I can already feel the itch to write a Cypher generation library :(

Thanks guys.

--
Matt Luongo
Co-Founder, Scholr.ly

Michael Hunger

unread,
Aug 7, 2012, 4:11:28 PM8/7/12
to ne...@googlegroups.com
Matt,

this issue is already on the list, to be able to specify the uniqueness per query. I think the old behavior was more likely a bug which manifested like this.

Michael

Wes Freeman

unread,
Oct 12, 2012, 6:59:54 PM10/12/12
to ne...@googlegroups.com
Was going through some of the old emails. Your original query works again in 1.9-SNAPSHOT, Matt.

Wes
Reply all
Reply to author
Forward
0 new messages