Unique constraint

Along with some other nodes I‘d like to have a user node. Every user has an username which has to be unique. Is it possible to achieve this in Dgraph?

1 Like

If you use graphql APIs, the id Directive is directly supported as a schema option to mark uniqueness for fields like username. https://graphql.dgraph.io/doc/schema/ids

2 Likes

I love it. :heart_eyes:

1 Like

But can there be multiple unique fields? E.g. Email also has to be unique.

1 Like

Not supported yet, but in the works. Please see this thread for reference.

1 Like

Thanks.
Just for me to understand it correctly: In every type there might be up to one “@id”. Am I correct?

Yes, that is correct. You can either use the ID type or the @id directive to establish a unique field.

So if a user has an email address I make a type named email and every email has an address with @id.
This is a workaround but until unique gets available. :man_shrugging:t3:

Agreed. Cant think of any better or more elegant way to handle this.

2 Likes

Sorry for bumping a fairly old topic, but this is the first result when searching for dgraph unique constraints on Google.

While the suggested method does sort of work, it has a bit of annoying drawback from what I can tell.

Say I set up a one-to-one relationship for my users to have a unique code:

type User {
  code: UniqueCode @hasInverse(field: user)
}

type UniqueCode {
  code: String! @id
  user: User!
}

Now say I create a new User and UniqueCode using the addUser mutation. And the UniqueCode is “CODE1”.

If I then try to create a second user and give it the same code as the previous user, I feel like the behavior I would like for a “true” unique constraint is an error. The behavior dgraph seems to have here though is to steal the UniqueCode reference from the first user and assign it to the second.

I’m not fully sure how to work around this at the moment.

If you notice the @id directive signifying the uniqueness is on the UniqueCode type. So across all of the nodes having the type UniqueCode, the db will attempt uniqueness through the GraphQL API.

Howver, there is nothing on the user that says it has to throw an error if using an existing UniqueCode vs a new one. This being a one-to-one relationship when you use an existing UniqueCode the API assumes you want it unmapped from the previous and mapped to the new one. There are use cases for this.

Why are you not putting the UniqueCode as a field of the User instead of a 1:1 edge? Maybe you have more fields in your actual use case.

I’m doing it as a reference in order to enforce uniqueness. Is there a way to have it directly on User and enforce that codes must be unique across all users? (Without setting it as an ID on user, codes are nullable and User already has a different ID)

Depending on your version, you can have multiple @id directives in one type

Thanks for the suggestion @amaster507 .

In my use case though, the unique code is actually nullable. I don’t think it’s possible to use String instead of String! for an @id field correct?

Correct.