Reputation: 421
I'm trying to execute a Cypher query like the following:
MATCH p = shortestPath((a:Party { currency: 'GBP' })-[:IN_ESCROW { status: 'cleared' }]-(b:Party { currency: 'USD' }))
However, it does not appear to be respecting the property constraint { status: 'cleared'} and is, instead, simply returning all of the shortest paths between the appropriately matched nodes that happen to be connected by :IN_ESCROW relations. While I can find no documentation alluding to this particular case, the documentation does clearly show that matching on relationship properties should be possible. Am I missing something or is this not possible to accomplish in Cypher?
Currently using community version 2.1.3 of Neo4j. Thank you in advance!
Upvotes: 3
Views: 2513
Reputation: 421
I have discovered the answer to my own inquiry. As it turns out, as of the 2.1.3 release I was using, shortestPath does not currently support filtering on relationship properties. There is, however, a slightly more expensive workaround available. Note that this is more expensive in the sense that it is slightly less performant than a filter on an indexed property may have been were that faculty supported by Cypher but it is by no means slow.
Rather than:
MATCH p = shortestPath((a:Party { currency: 'GBP' })-[:IN_ESCROW {
status: 'cleared'
}]-(b:Party { currency: 'USD' }))
You may match the shortestPath and then enforce property constraints through the use of predicates like so:
MATCH p = shortestPath((a:Party { currency: 'GBP' })-[r:IN_ESCROW]
-(b:Party { currency: 'USD' }))
WHERE all(x IN r WHERE x.status = 'cleared')
The drawback here is obviously that we are first matching on all possible shortest paths via :IN_ESCROW relations between the two matched nodes and then filtering to ensure that all of the relations contain the expected property. Personally, I find this behavior less than intuitive. It seems as if the shortestPath function might exclude desired results earlier simply because its matching blindly on the relation type, but in the wild this query works exactly as I needed it to.
So far, this has behaved for me as expected. Let's hope Neo4j nails down a solid syntax for doing property matching on relationships soon!
Upvotes: 3
Reputation: 66957
This seems to be your current model: (p1:Party)-[:IN_ESCROW]->(p2:Party)
.
Do you actually have an IN_ESCROW
relationship going in both directions between the parties in an escrow? If so, perhaps one of those relationships does not have status: 'cleared'
, thereby causing a match.
===
Also, apart from anything else, your model seems broken, since an escrow is an arrangement between 2 equal parties, so there does not seem to be any orderly way to determine which party should be the "head" of the relationship (p1
) and which should be the "tail" (p2
). And it makes it more likely that you will create (essentially redundant) relationships going in both directions.
I think this model would make more sense: (p1:Party)<-[:HAS_PARTY]-(e:Escrow)-[:HAS_PARTY]->(p2:Party)
.
Upvotes: 2