Paul W
Paul W

Reputation: 45

Using Parameters in Neo4j Relationship Queries

I'm struggling to work around a small limitation of Neo4j in that I am unable to use a parameter in the Relationship section of a Cypher query.

Christophe Willemsen has already graciously assisted me in working my query to the following:

MATCH (n1:Point { name: {n1name} }),
      (n2:Point { name: {n2name} }),
      p = shortestPath((n1)-[r]->(n2))
WHERE type(r) = {relType}
RETURN p

Unfortunately as r is a Collection of relationships and not a single relationship, this fails with an error:

scala.collection.immutable.Stream$Cons cannot be cast to org.neo4j.graphdb.Relationship

Removing the use of shortestPath() allows the query to run successfully but returns no results.

Essentially my graph is a massive collection of "paths" that link "points" together. It is currently structured as such:

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

I need to be able to provide a starting point (n1Name), an ending point (n2Name), and a single path to travel along (relType). I need a list of nodes to come out of the query (all the ones along the path).

Have I structured my graph incorrectly / not optimally? I am open to advice on whether the overall structure is not optimal as well as advice on how best to structure the query!

Upvotes: 0

Views: 771

Answers (2)

Christophe Willemsen
Christophe Willemsen

Reputation: 20185

EDIT

Regarding your edit, the nodes() function returns you the nodes along the path :

MATCH p=allShortestPaths((n:Point { name:"Point5" })-[*]->(n2:Point { name:"Point8" }))
WHERE ALL (r IN rels(p) WHERE type(r)={relType})
RETURN nodes(p)

In the console link, it is returning nodes Points 5,6,7,8


I guess in your case that using a common relationship type name for connecting your Point nodes would be more efficient.

If having a Path1, Path2, .. is for knowing the distance between two points, you can easily know the distance by asking for the length of the path, like this query related to your console link :

MATCH (n:Point { name:"Point1" })
WITH n
MATCH (n2:Point { name:"Point4" })
WITH n, n2
MATCH p=shortestPath((n)-[]->(n2))
RETURN length(p)

If you need to return only paths having a defined relationship length, you can use it without the shortestPath by specifying a strict depth :

MATCH (n:Point { name:"Point1" })
WITH n
MATCH (n2:Point { name:"Point4" })
WITH n, n2
MATCH p=(n)-[*3..3]->(n2)
RETURN length(p)
LIMIT1

As you can see here, the need to specify the relationship is not mandatory, you can just omit it or add the :NEXT type if you have other relationship types in your graph

If you need to match on the type, for e.g. the path from point 5 to point 8 in your console link, and the path can only have a PATH_TWO relationship, then you can do this :

MATCH (n:Point { name:"Point5" })
WITH n
MATCH (n2:Point { name:"Point8" })
WITH n, n2
MATCH p=(n)-[r*]->(n2)
WHERE type(r[0])= 'PATH_TWO'
WITH p, length(p) AS l
ORDER BY l
RETURN p, l
LIMIT 1

If you really NEED to have the Path1, Path2 style, maybe a short explanation on the need could help us find the more appropriate query

Upvotes: 1

Dirk Horsten
Dirk Horsten

Reputation: 3845

MATCH p=shortestpath((n1:Point{name:{n1name}})-[:relType *]->(n2:Point {name:{n2name}})) 
RETURN p

Upvotes: 0

Related Questions