Struggling with unique relationship constraints

Hi. I'm just getting started with neo4j. I'm running Community version 5.23.0 locally, and experimenting with the constraints I would want to be able to enforce if I were to decide to use neo in an upcoming project.
Unique relationship constraints exist, and are supported, but I can't get them to work in a way that makes any sense to me, and I feel I must be missing something basic.

CREATE (dave:Person {name: "Alice"});
CREATE (dave:Person {name: "Bob"});
CREATE (dave:Person {name: "Carol"});
CREATE (dave:Person {name: "Dave"});

CREATE CONSTRAINT person_related_to  FOR ()-[r:RELATED_TO]-() REQUIRE ( r.rtype)  IS UNIQUE;

MATCH (p:Person {name:"Alice"}) MATCH (q:Person {name: "Bob"}) CREATE (p)-[r:RELATED_TO  {rtype:"cousin"}]->(q);

So far so good.

But then...

MATCH (p:Person {name:"Carol"}) MATCH (q:Person {name: "Dave"}) create (p)-[r:RELATED_TO  {rtype:"cousin"}]->(q)

This fails with Relationship(1913) already exists with type ``RELATED_TO`` and property ``rtype`` = 'cousin'

I can't find any way to specify that the start and end nodes should be considered as relationship keys.

I know that duplicate relationships can be avoided by using MERGE, but I'd like to have constraints to avoid someone creating duplicates by forgetting to do so.

Can anyone help?

And can anyone explain when or how relationship constraints that don't take the start and end nodes into account would be useful?

EDIT: try to fix formatting.

That constraint will not work, as it states that only one relationship in the entire graph can type equal to 'cousin'. You can not define a relationship constraint based on the related nodes.

What are you trying to achieve?

I am trying to ensure that, whether someone remembers to us "MERGE" or not at any point in the future, they can't double-up the "cousin" link between two people. My actual use case may not even have a property - I would want only a single relationship of a given type to be allowed to exist between two nodes.

It looks like this just isn't possible, unless I duplicate a unique identifier for each node in the relationship - but that still doesn't give the schema integrity I'm looking for as the constraint would still be dependent on any future developer remembering to do the same thing.

For all practical purposes, you've answered my question - thanks, @glilienfield . It's now purely intellectual frustration left - I don't understand what the use of the relationship uniqueness constraint is at all, if there is no way to take the nodes into account.

The relationship uniqueness constraint is for a property. This would be used to ensure a unique identifier on relationships with a specific type. Consider it like a primary key.

I think you need to have your developers understand the difference between merge and create and use them appropriately.

I understand that in principle - just not when it would be useful.
Never mind. I'm just going to have to add it to the pile of things I'll probably never understand.
Thanks again for the quick reply.

Hi, most likely I don't get what you are trying to do, but just in case:

CREATE (j:Person {name:"John"}),
CREATE (p:Person) {name:"Peter"},
CREATE (j)-[:COUSIN]->(p)

Added 2 labels, created 2 nodes, set 2 properties, created 1 relationship, completed after 12 ms.

then if you try to merge:


MATCH (j:Person {name:"John"}), (p:Person {name: "Peter"})
MERGE (j)-[:COUSIN]->(p)

(no changes, no records)

Of course, if you merge a different relationship, maybe because it has a new property, then

MATCH (j:Person {name:"John"}), (p:Person {name: "Peter"})
MERGE (j)-[:COUSIN {newProp: "blah"}]->(p)

Set 1 property, created 1 relationship, completed after 12 ms.

No constraints are required.

Ah, just re-read your message. You want to avoid double create.

I understand now. But that is the reason why there is MERGE.

True people can make mistakes and use the wrong operation, but then they could also do DELETE, for example, not just CREATE. Do you need to prevent that too?

Enterprise Edition has Role Based Access Control to give different privilegies to different roles, but I do not think you can limit users to only use MERGE. The MERGE privilege also allows CREATE.

Thanks for the info @valerio.malenchino . If we decide to go with neo4j, we'll need to manage this in the application.