Reputation: 168
I am beginner to Neo4j, How to calculate the duration of the flight from A1 to A3. I am confused on doing the subtraction operation on the arrival and departure flights. I want to calculate the total time from A1 to A3 Airports. Here my Console http://console.neo4j.org/?id=g0mv8x
Really Appreciate for your cooperation!
Upvotes: 2
Views: 402
Reputation: 67019
This is indeed tricky, since you should not even be using the duration
property to do the calculation!
That is because multi-leg flights always have some lag time between the flights, which you need to consider when you calculate the total duration. Therefore, you need to subtract the arrival time of the last leg from the departure time of the first leg.
Judging from your sample data timestamps and duration values, it looks like your timestamps are in units of hours times 100. Caveat: the calculation is only possible if the timestamps incorporate date information, since the flight legs can span multiple days.
Here is how you can get all the practical flights from A1 to A3, along with the names of the start/end airports and the flightcodes for each leg:
MATCH (a:AIRPORT { name:"Airport A1" })-[c:Connect*]->(b:AIRPORT { name:"Airport A3" })
WHERE ALL(i IN RANGE(0, LENGTH(c)-2) WHERE (c[i+1]).dptrTime - (c[i]).arrvTime > 33)
RETURN a.name AS from, b.name AS to,
EXTRACT(x IN c | x.flightcode) AS flights,
(LAST(c).arrvTime - HEAD(c).dptrTime)/100.0 AS duration;
To ensure valid and practical itineraries, the WHERE
clause filters out itineraries that do not allow at least 20 minutes (33% of an hour) between each leg.
Here is a console that show these results:
+-----------------------------------------------------------+
| FROM | to | flights | duration |
+-----------------------------------------------------------+
| "Airport A1" | "Airport A3" | ["F2","F4"] | 4.0 |
| "Airport A1" | "Airport A3" | ["F1","F3"] | 5.0 |
| "Airport A1" | "Airport A3" | ["F5","F6","F7"] | 216.0 |
+-----------------------------------------------------------+
Note: The 216.0
hour duration comes from the arrival time of 23000
in your original sample data. This was probably a typo, but I left it unchanged.
You can modify the above query to get the fastest itinerary:
MATCH (a:AIRPORT { name:"Airport A1" })-[c:Connect*]->(b:AIRPORT { name:"Airport A3" })
WHERE ALL(i IN RANGE(0, LENGTH(c)-2) WHERE (c[i+1]).dptrTime - (c[i]).arrvTime > 33)
RETURN a.name AS FROM , b.name AS to, EXTRACT(x IN c | x.flightcode) AS flights,(LAST(c).arrvTime-HEAD(c).dptrTime)/100.0 AS duration
ORDER BY duration
LIMIT 1;
Results:
+------------------------------------------------------+
| FROM | to | flights | duration |
+------------------------------------------------------+
| "Airport A1" | "Airport A3" | ["F2","F4"] | 4.0 |
+------------------------------------------------------+
Upvotes: 3
Reputation: 18012
This one is a bit tricky. First the query, then the explanation:
MATCH p=shortestPath((a1:AIRPORT { name: "Airport A1" })-[*]-(a3:AIRPORT { name: "Airport A3" }))
RETURN reduce(totalDuration=0, duration IN
extract(leg IN relationships(p)| leg.duration) |
totalDuration + toInt(duration));
So first, you need to find the shortest path between the two. That's the first line. There are many paths, in general you want the cheapest/shortest.
Second, you then have a path. So the first thing you need to do is get all of the "durations" out of the relationships. That's what extract(leg IN relationships(p)| leg.duration)
does. Extract pulls something out of a collection. Finally, you need to sum them. That's what reduce
does. Notice that your durations are strings (they should be numerics) so you have to use toInt()
in order to convert it to a number that you can sum up.
Upvotes: 3