Neo4j Cypher: check attributes of non-consecutive nodes in a path

I have a schedule that represents several bus / train stops in different cities. Suppose I want to go from city A (with stops a1, a2, a3 ...) to city Z (with stops z1, z2 ...)

There are several routes (relationships) between nodes, and I want to get all paths between the beginning and end of the node. My cost vector would be complex (travel time and wait time and price, as well as ...) in fact, so I cannot use shortestpaths, etc. I managed to write a (rather complicated) query that does what I want: it searches for every match with starting A and ending Z, which is available.

I try to avoid the loop by filtering out results with special characteristics, for example. g.

MATCH (from{name:'a1'}), (to{name:'z1'}), path = (from)-[:CONNECTED_TO*0..8]->(to) WHERE ALL(b IN NODES(path) WHERE SINGLE(c IN NODES(path) WHERE b = c)) 

Now I want to avoid the opportunity to visit one city more than once, e. d. instead of a1 β†’ a2 β†’ d2 β†’ d4 β†’ a3 β†’ a4 β†’ z1 I want to get a1 β†’ a4 β†’ z1.

Therefore, I have to check all the nodes in the path. If the n.city value is the same for consecutive nodes, everything is fine. But if I have a path with nodes of the same city that are not consecutive, e. cityA β†’ cityB β†’ cityA I want to throw this way.

How can i do this? Is something possible?

I know that this is not a very beautiful approach, but I spent a lot of time searching for the best without dropping the whole data structure, but I could not find it. Its just a prototype and Neo4j is not my focus. I want to test some tools and products to create some knowledge. Next time I will start a better approach.

+5
source share
1 answer

Interest Ask. It is important to note here that the path that the city never reviews (after its exit) should have fewer crossings between cities than the number of individual cities. For instance:

  • AABBC ("good" way) has 3 different cities and 2 transitions
  • ABBAC (the β€œbad” way) also has 3 different cities, but 3 transitions

Given this observation, the following query should work (even if the start and end nodes are the same):

 MATCH path = ({name:'a1'})-[:CONNECTED_TO*0..8]->({name:'z1'}) WITH path, NODES(path) as ns WITH path, ns, REDUCE(s = {cnt: 0, last: ns[0].city}, x IN ns[1..] | CASE WHEN x.city = s.last THEN s ELSE {cnt: s.cnt+1, last: x.city} END).cnt AS nTransitions UNWIND ns AS node WITH path, nTransitions, COUNT(DISTINCT node.city) AS nCities WHERE nTransitions < nCities RETURN path; 

The REDUCE function is used to calculate the number of transitions in a path.

+1
source

Source: https://habr.com/ru/post/1261799/


All Articles