Shortest Path with Alternating Attributes

Hi everyone,

I'm working on a Neo4j project where I need to find a path between two pieces of equipment (i.e. from Equipment 552 to Equipment 554) through alternating pipe and hose/clip connections. The challenge is that the connections must alternate between pipe and hose/clip; there can never be pipe-to-pipe or hose-to-hose (or hose-to-clip) connections.

I have a hardcoded query that works for a specific path, like this:

MATCH (a:Equipment {name: "552"})
	-[r1:CAN_CONNECT_TO {type: "PIPE"}]->(p1:Port {name: "552-01"})
	-[r3:CAN_CONNECT_TO {type: "HOSE"}]->(p3:Port {name: "551-AA09"})
	-[r4:CAN_CONNECT_TO {type: "PIPE"}]->(p4:Port {name: "SPM-AA09"})
	-[r5:CAN_CONNECT_TO {type: "HOSE"}]->(p5:Port {name: "SPM-AA12"})
	-[r6:CAN_CONNECT_TO {type: "PIPE"}]->(p6:Port {name: "553-AA12"})
	-[r7:CAN_CONNECT_TO {type: "CLIP"}]->(p7:Port {name: "554-OH"})
	-[r8:CAN_CONNECT_TO {type: "PIPE"}]->(p8:Equipment {name: "554"})
RETURN a, p1, p3, p4, p5, p6, p7, p8

However, this approach doesn't scale well and becomes slower as the path length increases. I also tried a more generic query that allows for variable path lengths:

MATCH path = (source:Port {name: '552-01'})
  -[l1:CAN_CONNECT_TO]->(:Port)
  -[:CAN_CONNECT_TO {type: 'PIPE'}]->(:Port)
  -[l2:CAN_CONNECT_TO]->(:Port)
  -[:CAN_CONNECT_TO {type: 'PIPE'}]->(:Port)
  -[l3:CAN_CONNECT_TO]->(:Port)
  -[:CAN_CONNECT_TO {type: 'PIPE'}]->(:Port)
  -[l4:CAN_CONNECT_TO]->(:Port)
  -[:CAN_CONNECT_TO {type: 'PIPE'}]->(:Port)
  -[l5:CAN_CONNECT_TO]->(target:Port {name: '554-OH'})
WHERE NOT 'PIPE' IN [l1, l2, l3, l4, l5]
RETURN source, [n IN nodes(path) | n.name] AS nodes, target

But this still has performance issues and doesn't seem to be the most efficient way to handle the problem.

I'm looking for a way to structure a Neo4j query, either with a projection, or a different query structure, to optimize this alternating pipe/hose connection problem. The goal is to find a path from Equipment 552 to Equipment 554 without specifying the details of the intermediate connections in the query itself.

I need to set these possible paths, and then use one of the shortest path algorithms to determine which one to select, so that I can provide a user with the top 10 fastest paths.

I started trying to dig into using path expansion, based off a separate post here a colleague of mine made a while ago, but am not getting this to match as I work through it.

MATCH (a:Equipment {name: "552"}), (b:Equipment {name: "554"})
CALL apoc.path.expandConfig(a, {
relationshipFilter: "CAN_CONNECT_TO{type:'PIPE'}, CAN_CONNECT_TO{type:'HOSE'}|CAN_CONNECT_TO{type:'CLIP'}",
endNodes: [b],
minLevel: 1,
maxLevel: 10,
bfs: true
})
YIELD path
RETURN path 

This query returns nothing, even though I can confirm there is a valid path, based off my hardcoded query working fine

Can anyone suggest a more efficient and scalable approach to solve this problem? I'd really appreciate any insights or ideas you might have.

Thanks in advance for your help!

Best regards,
Keith