Motivation
@id
fields in GraphQL are currently not editable. Once entered we can’t change the value of these fields. Also, these fields are currently non-nullable.
Also we can now have multiple @id fields in a type, having all of them non-nullable is not a good design.
These improvements on @id
fields are pending for some time now and asked by many users and have use cases around them. Also, we now have a much simpler mutation rewriting code that will allow us to do change this behavior much quickly.
Implementation
Here, I will go over a couple of things we need to change to have editable and nullable @id
fields.
Changes in update mutation
-
Currently @id fields are not added to update mutation patch, firstly we need to add them to update mutation patch.
-
While doing update mutation, we need to make an existence query (same as we do in addition case) to check if there exists a node for a given value of the
@id
field or not. Based on that result we need to give an error or update the field.
Also, we need to take care of inherited unique@id
fields which are unique across all the implementing types of the interface. The process will be similar as adding a node.
Inherited unique@id
fields are being added and change is currently in review
Feat(GraphQL): This PR allows @id field in interface to be unique across all the implementing types. by JatinDevDG · Pull Request #7710 · dgraph-io/dgraph · GitHub -
While doing update mutation, we need to give filter to select nodes to update.If filter results in multiple nodes, then updation of
@id
field not possible because we can’t have same value of@id
field for multiple nodes. We can give error if filter results in multiple nodes, and it will be best practice for users to give@id
field in filter itself, whenever possible.
But it can also happen that none of the@id
fields is present for the node as we are now making@id
fields non-nullable. Then in some cases, there is no way to filter that particular node.
The solution to this is to enforce at least one @id field non-nullable, something like primary key.
Changes in Add mutation with upsert
This case is much complex. Currently, while doing Add mutation with upsert we use given @id
fields in mutation to search existing nodes. if any of the @id
fields exist in some node we return that node and otherwise, we add the node with all of the given fields.
And if there are multiple @id
fields and there are multiple nodes corresponding to them then we select a node randomly and update all fields apart from @id
field.
Note: This behaviour also needs to be fixed , we need to give flexibility to users to select an @id
field which will be used to search the nodes while doing upserts when multiple nodes are present.
Now , If we make @id
field mutable then there is no way to search the existing node because we use @id fields to search a node in upserts and that itself can be updated. For this, we can change the design to have a primary @id
field that user can specify in the schema that will be used to do upserts(in that case primary @id field is not update able), or user needs to define which @id
field they want us to use for upserts.
And also as we are making @id fields nullable then it is also possible that in add mutation no @id is present then also we don’t have a way to do upserts. That can again be solved by having primary @id field that is not nullable.
As of now, we are thinking of not changing the upsert behaviour and if user need to update the @id
field then they can use update mutation.
References:
RFC: Allow multiple unique fields in graphql schema
Editable @id fields
Nullable @id field