Reputation: 23
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
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