The shortest path is pretty easy:
MATCH path=shortestPath((station_44:STATION {id:44})-[*0..10]-(station_46:STATION {id:46}))
RETURN path
As far as counting transfers you can do something like this:
MATCH path=allShortestPaths((station_44:STATION {id:44})-[rels*0..10]-(station_46:STATION {id:46}))
RETURN length(path) AS stop_count, length(FILTER(index IN RANGE(1, length(rels)-1) WHERE (rels[index]).bus <> (rels[index - 1]).bus)) AS transfer_count
Once you have those two variables you can calculate / sort however you like. For example:
MATCH path=(station_44:STATION {id:44})-[rels*0..4]-(station_46:STATION {id:46})
WITH length(path) AS stop_count, length(FILTER(index IN RANGE(1, length(rels)-1) WHERE (rels[index]).bus <> (rels[index - 1]).bus)) AS transfer_count
RETURN stop_count, transfer_count
ORDER BY (stop_count * 0.5) + (transfer_count * 2.0) DESC
Here I removed the allShortestPaths
call so that you get different lengths of paths. The ORDER BY
uses weights on the two metrics. Unfortunately, at least in my DB, if you go beyond a path length of four it starts to get really slow. You might be able to improve that by introducing a direction arrow in the path, if that makes sense in your case.