Wall
Wall

Reputation: 313

Neo4j loop for all children

In Neo4j I got the following nodes: enter image description here

As you can see, they are siblings connected by relationships as NEXT or NEXT_SIBLING; moreover, the first and last child are connected to the father by FIRST_CHILD_OF and LAST_CHILD_OF.

I simply want to find a way to cycle them in order to create a single string which is "A B C D".

Is there a Cypher query capable of this?

Upvotes: 1

Views: 468

Answers (1)

ThirstForKnowledge
ThirstForKnowledge

Reputation: 1304

Creating your model

For the ease of possible further answers and solutions I note my graph creating statement:

CREATE
  (ormText:OrmText {name: 'orm_Text'})<-[:FIRST_CHILD_OF]-(letterA:Letter {name: 'A'}),
  (letterA)-[:NEXT]->(letterB:Letter {name: 'B'}),
  (letterA)-[:NEXT_SIBLING]->(letterB),
  (letterB)-[:NEXT]->(letterC:Letter {name: 'C'}),
  (letterB)-[:NEXT_SIBLING]->(letterC),
  (letterC)-[:NEXT]->(letterD:Letter {name: 'D'}),
  (letterC)-[:NEXT_SIBLING]->(letterD),
  (letterD)-[:LAST_CHILD_OF]->(ormText);

graph

Solution

MATCH
  letterPath = (startLetter)-[:NEXT|NEXT_SIBLING*]->(endLetter)
WHERE 
  (startLetter)-[:FIRST_CHILD_OF]->(:OrmText)<-[:LAST_CHILD_OF]-(endLetter)
WITH nodes(letterPath) AS letterNodes
UNWIND letterNodes AS letterNode
RETURN DISTINCT letterNode.name AS letterName;

The second line detects the startLetter as first child of orm_Text and the endLetter as last child of orm_Text. In line five the path between the start and end letter is calculated, its nodes were extracted in line six. Line seven creates singles nodes and line eight finally returns the result.

Note: By writing -[:NEXT|NEX_SIBLING*]-> a relationship of type NEXT or NEXT_SIBLING is valid for a match. If your requirement only need one specific type, remove the other and the |.

Result

╒════════════╕
│"letterName"│
╞════════════╡
│"A"         │
├────────────┤
│"B"         │
├────────────┤
│"C"         │
├────────────┤
│"D"         │
└────────────┘

Extension

If you prefer your output in a single String instead of a list of node names have a look at the following solution.

Solution

MATCH
  letterPath = (startLetter)-[:NEXT|NEXT_SIBLING*]->(endLetter)
WHERE 
  (startLetter)-[:FIRST_CHILD_OF]->(:OrmText)<-[:LAST_CHILD_OF]-(endLetter)
WITH nodes(letterPath) AS letterNodes
RETURN DISTINCT reduce(s=head(letterNodes).name, n in tail(letterNodes) | s+" -> "+n.name) AS letterString;

Result

╒══════════════════╕
│"letterString"    │
╞══════════════════╡
│"A -> B -> C -> D"│
└──────────────────┘

Upvotes: 2

Related Questions