Reputation: 35
I have a set of nodes and relationships and I want to get subgraph of a particular type for a node. To explain the question, attached the image for the graph.
Nodes in yellow are connected by nodes in green by a relation "IS_PART_OF". When we look at the above fragment, yellow node "8366854" is connected by 4 green nodes "P10398", "P10398-2", "A0A024" and "P02647" where yellow node "8366931" is connected by 2 green nodes "A0A024" and "P02647". So green nodes "A0A024" and "P02647" are common to both and I could say yellow node "8366931" is a sub of "8366854". This happens only if all green nodes are common to both.
So my query will be a yellow node id say "8366854", which returns all sub yellow nodes (in this case only "8366931").
So in this way for the below fragment, I could say,
1) "8366523" is sub of "8366848"
2) "8366915" not a sub of "8366848" since it doesn't have all green nodes in common.
Upvotes: 2
Views: 537
Reputation: 1304
The first statement creates the nodes, the second the relationships between them.
CREATE
(Yellow1:Yellow {name: 'Yellow 1'}),
(Yellow2:Yellow {name: 'Yellow 2'}),
(Yellow3:Yellow {name: 'Yellow 3'}),
(Yellow4:Yellow {name: 'Yellow 4'}),
(Yellow5:Yellow {name: 'Yellow 5'}),
(Yellow6:Yellow {name: 'Yellow 6'}),
(Green1:Green {name: 'Green 1'}),
(Green2:Green {name: 'Green 2'}),
(Green3:Green {name: 'Green 3'}),
(Green4:Green {name: 'Green 4'}),
(Green5:Green {name: 'Green 5'}),
(Green6:Green {name: 'Green 6'}),
(Green7:Green {name: 'Green 7'}),
(Green8:Green {name: 'Green 8'}),
(Green9:Green {name: 'Green 9'}),
(Green10:Green {name: 'Green 10'}),
(Green11:Green {name: 'Green 11'}),
(Green12:Green {name: 'Green 12'}),
(Green13:Green {name: 'Green 13'})
CREATE
// upper graph
(Green1)-[:IS_PART_OF]->(Yellow1),
(Green2)-[:IS_PART_OF]->(Yellow1),
(Green3)-[:IS_PART_OF]->(Yellow1),
(Green4)-[:IS_PART_OF]->(Yellow1),
(Green3)-[:IS_PART_OF]->(Yellow2),
(Green4)-[:IS_PART_OF]->(Yellow2),
// lower graph
(Green5)-[:IS_PART_OF]->(Yellow3),
(Green6)-[:IS_PART_OF]->(Yellow3),
(Green5)-[:IS_PART_OF]->(Yellow4),
(Green6)-[:IS_PART_OF]->(Yellow4),
(Green7)-[:IS_PART_OF]->(Yellow4),
(Green8)-[:IS_PART_OF]->(Yellow4),
(Green7)-[:IS_PART_OF]->(Yellow5),
(Green8)-[:IS_PART_OF]->(Yellow5),
(Green9)-[:IS_PART_OF]->(Yellow5),
(Green10)-[:IS_PART_OF]->(Yellow5),
(Green11)-[:IS_PART_OF]->(Yellow5),
(Green12)-[:IS_PART_OF]->(Yellow5),
(Green8)-[:IS_PART_OF]->(Yellow6),
(Green13)-[:IS_PART_OF]->(Yellow6);
For a yellow node "this" compare the amount of relationships to an other yellow node "that" with the amount of all relationships of node "this". If the amount is equal, node "this" is a sub of "that".
// |-------------------------------------- (1) ---------------------------------------|
MATCH yellowPairPath = (yellowA:Yellow)<-[pairRelation:IS_PART_OF]-(:Green)-[:IS_PART_OF]->(yellowB:Yellow)
WITH DISTINCT yellowA, yellowB, pairRelation
// |-------- (2) --------|
WITH yellowA, startNode(pairRelation) AS pairRelations, yellowB
// |------- (3) ------|
WITH yellowA, count(pairRelations) AS pairRelationAmount, yellowB
// |---------------------- (4) -----------------------|
MATCH (yellowA:Yellow)<-[allRelations:IS_PART_OF]-(:Green)
// |------ (5) ------|
WITH yellowA, pairRelationAmount, count(allRelations) AS allRelationsAmount, yellowB
// |---------------- (6) ----------------|
WHERE pairRelationAmount = allRelationsAmount
RETURN yellowA, yellowB;
Regarding your requirements, the result has to be interpreted as "YellowA is a sub of YellowB" for the listed nodes.
╒═══════════════════╤═══════════════════╕
│"yellowA" │"yellowB" │
╞═══════════════════╪═══════════════════╡
│{"name":"Yellow 2"}│{"name":"Yellow 1"}│
├───────────────────┼───────────────────┤
│{"name":"Yellow 3"}│{"name":"Yellow 4"}│
└───────────────────┴───────────────────┘
Upvotes: 0
Reputation: 29167
Actually, the cypher allows you to express this by a sequence of instructions:
MATCH (Y1:YELLOW)<-[:IS_PART_OF]-(G:GREEN)
WITH Y1,
collect(G) AS greens1
UNWIND greens1 AS G
MATCH (G)-[:IS_PART_OF]->(Y2:YELLOW)<-[:IS_PART_OF]-(G2:GREEN) WHERE Y1 <> Y2
WITH Y1, Y2, greens1,
collect(G2) AS greens2
WHERE SIZE(greens1) > size(greens2) AND
ALL(G IN greens2 WHERE G IN greens1)
RETURN Y1, collect(Y2) AS subs
Upvotes: 1