cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Constraint to prevent certain relations

masavini
Node Link

Hi,
please consider the following graph:Screenshot_20230113_221202.png

CREATE (n0:Person {name: "Jack"})-[:ALLIED_WITH]->(n4:Person {name: "Theo"})-[:ENEMY_OF]->(n3:Person {name: "Paul"})<-[:PARTNER_OF]-(:Person {name: "Jim"})-[:ALLIED_WITH]->(n1:Person {name: "Mark"})-[:PARTNER_OF]->(:Person {name: "Bill"})<-[:ENEMY_OF]-(n0),
(n3)-[:ALLIED_WITH]->(n1),
(:Person {name: "Deb"})-[:PARTNER_OF]->(n4)

As you can see, I have 2 groups of nodes (yellow and green nodes). The nodes are linked within each group with "positive" relations ([PARTNER_OF] and [ALLIED_WITH]), while nodes of different groups have just "bad" relations ([ENEMY_OF], in the example).

Is it possible to create a constrain to prevent the creation of "positive" relations ('PARTNER_OF' and 'ALLIED_WITH', in this example) between nodes of different groups?

Thanks for your help!

4 REPLIES 4

Cypher does not have a constraint like this.  You could try to use an apoc trigger to execute when a new relationship is created. You may be able to raise an exception if the new relationship relates two nodes in different groups.

https://neo4j.com/labs/apoc/4.4/background-operations/triggers/

https://neo4j.com/labs/apoc/4.4/overview/apoc.util/apoc.util.validate/

@masavini 

futher tto @glilienfield   but Neo4j constraint functionality is described at

https://neo4j.com/docs/cypher-manual/4.4/constraints/

 

masavini
Node Link

Thanks for your hints, but I'm afraid this is getting too complicated for me. Do you think changing the graph schema could help to simplify it?

masavini
Node Link

What do you think about this solution?

 

//avoid enemies
PROFILE
// create wrong relation
MATCH (p1:Person {name: 'Deb'}), (p2:Person {name: 'Mark'})
MERGE (p1)-[r:PARTNER_OF]->(p2)
// check cluster
WITH p1, r
    MATCH (p1)-[:PARTNER_OF|ALLIED_WITH*]-(ps)
WITH p1, r, collect(DISTINCT ps) as nodes
    UNWIND [p1] + nodes as s
        MATCH (s)-[:ENEMY_OF]-(e) WHERE NOT s.name = e.name AND e IN nodes
WITH r, collect(DISTINCT e) as enemies
FOREACH (i in
    CASE WHEN not enemies = [] THEN [1] ELSE [] END | DELETE r
)

 

Could you suggest how to break the UNWIND loop as soon as line 11 MATCH finds the first result?
Thanks!