4

One bill of material relationship is composed of two relationships. I then find my component definition by searchin this relationship :

(a:Part)-[:consumes]->(b:partBom)-[:referencedBy]->(c:Part)

How can I repeat this pattern in a cypher request in order to find n levels of my bill of material ?

2 Answers2

3

Yoann,

As a follow-on to Michael's answer, if you capture the path in a query of the form

MATCH (a:Part), p=(a)-[:consumes|referencedBy*2..]->(c:Part)
WHERE NOT (c)-[:consumes]->()
WITH a, rels(p) AS rs, nodes(p) AS ns
WITH a, rs, ns, FILTER(n IN ns WHERE 'partBom' IN LABELS(n)) AS boms, FILTER(n in ns WHERE 'Part' in LABELS(n)) AS parts

any following clauses have access to all of the nodes and relationships in the collections ns and rs, and to the BOMs in the collection boms, and the parts in collection parts. The query fragment above will match all of the longest chains of your pattern. You can read more about this relationship pattern concept in the Neo4j manual at this link. You might want to put an upper bound on the number of hops in the initial match if there is a chance of looping.

Grace and peace,

Jim

Jim Biard
  • 2,252
  • 11
  • 14
1

If you know the number of levels, then you can just spell them out.

(a:Part)-[:consumes]->(b:partBom)-[:referencedBy]->(c:Part)
(c)-[:consumes]->(d:partBom)-[:referencedBy]->(e:Part)
....

Or you can do it more dynamic.

(a:Part)-[:consumes|referencedBy*8]->(c:Part)
WITH rels(path) as rels, nodes(path) as nodes
WHERE ALL(idx in range(0,length(rels)-1,2) WHERE type(rels[idx]) = 'consumes') 
  AND ALL(idx in range(1,length(rels)-1,2) WHERE type(rels[idx]) = 'referencedBy')
  AND ALL(idx in range(1,length(nodes)-1,2) WHERE labels(nodes[idx])[0] = 'partBom') 

Usually for something like this, I'd look into the Java API for efficient incremental evaluation of something like that.

Michael Hunger
  • 41,339
  • 3
  • 57
  • 80
  • So I take it there is no way to do something like this bogus query? `(a:Part)-([:consumes]->(b:partBom)-[:referencedBy])*->(c:Part)` – Kevin Krumwiede Sep 09 '14 at 06:29
  • That's the issue. I don't know the depth of the structure I'm browsing. It would be very nice if I could define a relationship like MYREL = `[:consumes]->(b:partBom)-[:referencedBy]` and then browser recursively on this rel – Yoann Maingon Sep 09 '14 at 08:07
  • Sure you can just replace the 8 by a higher number, or leave it off and then check the path length. – Michael Hunger Sep 10 '14 at 12:22
  • I mean, notice how I used a Kleene star to indicate repetition of that sequence of two relationships. My understanding is that there is no real syntax to express that in Cypher. This differs from `[:consumes|referencedBy*8]` because the latter would match two `consumes` in a row, which is not quite what the OP and I are looking for. – Kevin Krumwiede Sep 14 '14 at 02:16