Marthinus Engelbrecht
Marthinus Engelbrecht

Reputation: 451

Can you create a uniqueness constraint for the relationship between all nodes that fall under two labels in neo4j?

I have the following labels:

Their relationships is as follows:

As an example, if the below query is run twice it will succeed.

CREATE (:Product { name: "Chocolate"})-[:is_of]->(:Brand {name: "Cadbury"})

And the graph result for the below query can be seen in the image here

MATCH (p:Product { name: "Chocolate"})-[:is_of]->(b:Brand {name: "Cadbury"}) RETURN p,b 

As you can see there is 2 "Chocolate" product nodes and 2 "Cadbury" brand nodes.

I would like to enforce that when creating a product there is only one product node with property name = "Chocolate" that has an is_of relationship with a brand with property name = "Cadbury". So the above CREATE query would fail on the second attempt with some message like: There is already one product node with a name = "Chocolate" and a brand of "Cadbury". This is prohibited by a constraint.

The relational database analog would be a primary key that stretches over multiple foreign keys. For example, adding the below to table Product where table Brand has a primary key Brand ID:

PRIMARY KEY("Product ID","Brand ID")

I've tried placing a constraint on a property of the Brand to only allow unique brands. But the problem is you can still create two products that is_of the same brand. I don't want to create a unique constraint on product name as well because there can be multiple "Chocolate" products from different brands.

I've read through the documentation but it seems that constraints can only be placed on properties...

I would imagine syntax that would look something like below:

CREATE CONSTRAINT ON g=(p:Product)-[:is_of]->(b:Brand) ASSERT g IS UNIQUE FOR p.name, b.name

Upvotes: 2

Views: 1444

Answers (3)

LPLP1313
LPLP1313

Reputation: 77

Adding an update to this older thread as this comes up with constraint search results.

What you're trying to do requires an Enterprise license. You can enforce constraints on paths ()-[]-() when you have an enterprise license. You can also use scenarios with multiple attributes.

As an FYI, I would turn your arrows the other way as IMHO brands have a relationship (directed) to their products. It might enable the constraint to be enforced with the non-enterprise version a bit easier as well. Just a thought.

Upvotes: 0

Eve Freeman
Eve Freeman

Reputation: 33175

The short answer is No.

There has been talk about having arbitrary pattern syntax for constraints in Neo, but it's not there or on the roadmap as of yet, AFIAK. The closest I've found in the wild is in an unmerged CIP in an unofficial repo:
https://github.com/Mats-SX/openCypher/blob/88c0f11f11410ce2f68dc050e54ff419058c6cad/cip/1.accepted/CIP2016-12-14-Constraint-syntax.adoc

See documentation for current available constraint syntax:
https://neo4j.com/docs/developer-manual/current/cypher/schema/constraints/

The closest you can come in 3.3.x, I think, is converting that :is_of relationship to a node and putting properties on it that you can make a node key with.

Upvotes: 1

Bruno Peres
Bruno Peres

Reputation: 16375

Maybe you can try using MERGE instead of CREATE. The docs about MERGE says:

The MERGE clause ensures that a pattern exists in the graph. Either the pattern already exists, or it needs to be created.

So running the following Cypher command twice

MERGE (:Product { name: "Chocolate"})-[:is_of]->(:Brand {name: "Cadbury"});

will produce the following graph:

Result

Upvotes: 1

Related Questions