Motivation
With the support of external IDs using @id
directive, users of Dgraph GraphQL often face a situation where the existence of a particular ID in database decides on whether a particular mutation should be carried out or not. One such common example is described below:
Schema:
type Person {
id: String! @id
name: String!
}
Suppose, a user wants to perform a mutation to set name
field of Person with id "2"
to "New Name"
, the current way to do this using GraphQL would involve following steps:
- Use
queryPerson
with appropriate filters to find out if a there existsPerson
withid = "2"
- If there exists a Person with
id = "2"
, carry out anupdatePerson
mutation. - If there does not exist any such
Person
, create a new Person withid = "2"
and set its name to"New Name"
usingaddPerson
mutation.
All these steps need to be performed from Client side. This proves out to be cumbersome.
A GraphQL mutation which will replace this 3 step process has been requested by Users many times.
Here are some of the related discuss posts:
- How to upsert using GraphQL?
- GraphQL equivalient to Insert on Duplicate Key Update
- Converting update query to an upsert query
- Upsert in gql
- Upsert equivalent on dgraph
To help address these issues, we propose Upsert Mutations using GraphQL
Proposal
We propose adding another variable, upsert
to the input of add
GraphQL Mutations.
Current addPerson Mutation:
mutation{
addPerson(input: [AddPersonInput!]!): AddPersonPayload
}
Proposed addPerson Mutation after adding upsert
as input variable:
mutation{
addPerson(input: [AddPersonInput!]!, upsert: Boolean): AddPersonPayload
}
Along with providing input
value to add
Mutation, this will enable Users to provide an optional upsert
Boolean value. Setting upsert
to True
while carrying out add
mutation will change the behaviour of add Mutation to an upsert.
The default value of upsert
will be False
. This is done to ensure backward compatibility.
In the above discussed case, the three steps could then be replaced by a single add mutation:
addPerson(input: [ { "id": "2", name: "New Name" } ] , upsert: True)
Limitations
- Deep GraphQL mutations:
The current behaviour of Add and Update Mutations is such that other than at root level, existing nodes with XID (@id directive) are not updated. This behaviour will continue to maintain backward capability. Add mutations withupsert
set toTrue
will only affect the root level nodes and will update the values (if already existing) at root level only. - Setting
upsert
value toTrue
in an Add mutation for a Type which does not contain any@id
will have not effect.upsert
will only be relevant for Types containing an@id
field.
@amaster507, @iyinoluwaayoola, @andrewluetgers, @phillip, @billybobthorton We will like to know more from you on whether this fits your use case.