Reputation: 1601
I'm trying to model flights between airports on certain dates. So far my test graph looks like this:
Finding shortest path between for example LTN and WAW is trivial with:
MATCH (f:Airport {code: "LTN"}), (t:Airport {code: "WAW"}),
p = shortestPath((f)-[]-(t)) RETURN p
Which gives me:
But I have no idea how to get only paths with Flights that have relation FLIES_ON with given Date.
Upvotes: 9
Views: 7123
Reputation: 7790
Here's what I would do with your given model. The other commenters' queries don't seem right, as they use ANY()
instead of ALL()
. You specifically said you only want paths where all Flight
nodes on the path are attached to a given Date
node with a :FLIES_ON
relationship:
MATCH (LTN:Airport {code:"LTN"}),
(WAW:Airport {code:"WAW"}),
p =(LTN)-[:ROUTE*]-(WAW)
WHERE ALL(x IN FILTER(x IN NODES(p) WHERE x:Flight)
WHERE (x)<-[:FLIES_ON]-(:Date {date:"130114"}))
WITH p ORDER BY LENGTH(p) LIMIT 1
RETURN p
http://console.neo4j.org/r/xgz84y
Upvotes: 4
Reputation: 20175
The problem is that using shortestPath or allShortestPaths will never include the Date nodes.
What you need to do is to filter the pattern with the date node (I don't know however how you store the date, so I'll take Ymd format:
MATCH (f:Airport {code: "LTN"}), (t:Airport {code: "WAW"})
MATCH p=(f)-[*]-(t)
WHERE ANY (r in rels(p) WHERE type(r) = 'FLIES_ON')
AND ANY (n in nodes(p) WHERE 'Date' IN labels(n) AND n.date = 20150120)
RETURN p
ORDER BY length(p)
LIMIT 1
Another solution and less costly, is to include the date in your match and building yourself the path with it :
MATCH (n:Date {date:20150120})
MATCH (f:Airport {code:"LTN"}), (t:Airport {code:"WAW"})
MATCH p=(f)<-[*]-(n)-[*]->(t)
RETURN distinct(p)
ORDER BY length(p)
Upvotes: 0
Reputation: 1022
though this would not be my preferred structure for this kind of data; in answering your question i might go this way instead. get the paths, filter the path and get the first one ordered by length.
in the console tests is runs faster than the one suggested above as the query plan is simpler.
Anyhoo i hope this at least points you in a good direction :)
MATCH (f:Airport { cd: "ltn" }),(t:Airport { cd: "waw" }), p =((f)-[r*]-(t))
WHERE ANY (x IN relationships(p)
WHERE type(x)='FLIES_ON') AND ANY (x IN nodes(p)
WHERE x.cd='130114')
RETURN p
ORDER BY length(p)
LIMIT 1
Upvotes: 0