1. Creating your graph:
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);
2. Proposed solution:
2.1 Underlying idea:
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".
2.2 Explanation:
- identify all pairs between two yellow nodes
- identify all green nodes within the yellow-yellow pairs
- count the amount of green nodes within a yellow-yellow pair
- identify all relationships of the yellow node under inspection
- count the amount of all relationships for the yellow node under inspection
- filter those yellow-yellow pairs, where the amount of all relationships is equal to the amount of the pair relationships
2.3 Cypher statement:
// |-------------------------------------- (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;
3. Result:
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"}│
└───────────────────┴───────────────────┘