Traversal across intermediate nodes

I am modelling Software components and their interfaces. A simplified model contains the following labels: SoftwareComponent and Interface. A software component may provide 0 or more Interfaces, and utilize 0 or more interfaces.

An example may look like this:

espen_solbu_0-1656936984272.png

Note that in the real model, both the components and the interfaces has additional relationships to "other things" (aka what they carry, protocols, etc)

I want to write a query that allows me to return the paths to all "downstreams" components from an anchor component.

I have managed to write queries that return almost what i want, but I don't think i'm doing it right...

Closest I have gotten is:

match (p:Component) where p.name STARTS WITH 'A'
WITH p
match path=(p)-[:PROVIDES|UTILIZES*1..5]-(n) WHERE (n:Component or n:Interface) AND (n)-[:UTILIZES]-()
return path

(Since I try to capture multiple (Component)-PROVIDES->(Interface)<-UTILIZES-(Component), I cannot use direction on those relationships)

However, I have been unable to restrict this to only show the paths that are downstreams. Aka i'd like the full path from p, (:Component)-PROVIDES->(:Interface)<-UTILIZES-(:Component), all the way down to the bottom Component or Interface.

Also if i remove the relationship restriction (5 in the example), the query now takes forever.

I am sure there must be a better way to collect all the downstream interfaces and components. Any suggestions?

regards

Espen

Thanks! that worked perfectly!

I guess there isnt a way to do "arbitrary lengths of subqueries" in native cypher?

Two comments for others reading this thread:

  • typo in the query in the acccepted answer, need a comma after "Component|Interface" in the answer above
  • One can remove the maxLevel: 5 entry to make it go out further

Hi @espen_solbu !

Have you already installed APOC? If you haven't... do it. :smile: In any case, something like this may work:

match (p:Component) where p.name STARTS WITH 'A'
WITH p
CALL apoc.path.spanningTree(p, {
    relationshipFilter: "PROVIDES>|<UTILIZES",
    labelFilter: "Component|Interface",
    minLevel: 1,
    maxLevel: 5 //??
})
YIELD path
with path //, last(nodes(path)) as n ??
//where not (n)<-[:UTILIZES]-() ??
RETURN path

Hi @espen_solbu,

I solved the first type. Sorry about that. Yes, you can remove the min and max level as well as play with other variables. Native Cypher supports arbitrary lengths but it will not do it based on directions sub patterns (yet :wink:).

Lemme know if I can help you in any other way

Bennu