szk
szk

Reputation: 23

Neo4j cypher: Find all paths till node of certain type

In Neo4j I have stored data with nodes of type A and B. Between 2 nodes A there could be many nodes of type B. I would like to fetch first node of type A for each path outgoing from a given node A. I post example structure below.

  /->A2->A3
A1-->A4->A5
  \->B1->A6

For input: A1, I would like my query to return only A2, A4 and A6.

Query that I'm using right now is below:

 MATCH p=(source:Node ) - [:relation*] -> (target:Node) WHERE
 source.name = "A1" AND target.type = "A" RETURN target

However it returns nodes A3 and A5 which I want to get rid of.

Upvotes: 1

Views: 1491

Answers (1)

Bruno Peres
Bruno Peres

Reputation: 16355

I have used this sample data set to reproduce your scenario:

create (root:Node {name : "A1", type: "A"})-[:LINKED_TO]->(:Node{name : "A2", type: "A"})-[:LINKED_TO]->(:Node{name : "A3", type: "A"}),
(root)-[:LINKED_TO]->(:Node{name : "A4", type: "A"})-[:LINKED_TO]->(:Node{name : "A5", type: "A"}),
(root)-[:LINKED_TO]->(:Node{name : "B1", type: "B"})-[:LINKED_TO]->(:Node{name : "A6", type: "A"})

Then, this query, using filter() function:

// MATCH all paths between source and target, starting from 2 hops.
// target node should be the last node of the path.
MATCH p=(source:Node)-[:LINKED_TO*]->(target:Node)
WHERE source.name = "A1" AND target.type = "A" AND NOT (target)-->()
// grouping by path, I have filtered the nodes of each path, getting only ones that have type = "A"
// then I get the first one by index (index [0])
WITH p, filter(node IN nodes(p)[1..] WHERE node.type = "A")[0] as firstA
// return the firstA node
RETURN firstA

The output:

╒════════════════════════╕
│"firstA"                │
╞════════════════════════╡
│{"name":"A6","type":"A"}│
├────────────────────────┤
│{"name":"A4","type":"A"}│
├────────────────────────┤
│{"name":"A2","type":"A"}│
└────────────────────────┘

Tip: instead of a property named type you can add another label for each node denoting your type, like :A and :B. Remember that labels are ideal for grouping nodes into sets. Also, a node can have more than one label.

Upvotes: 2

Related Questions