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
queryPersonwith appropriate filters to find out if a there existsPersonwithid = "2" - If there exists a Person with
id = "2", carry out anupdatePersonmutation. - If there does not exist any such
Person, create a new Person withid = "2"and set its name to"New Name"usingaddPersonmutation.
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 withupsertset toTruewill only affect the root level nodes and will update the values (if already existing) at root level only. - Setting
upsertvalue toTruein an Add mutation for a Type which does not contain any@idwill have not effect.upsertwill only be relevant for Types containing an@idfield.
@amaster507, @iyinoluwaayoola, @andrewluetgers, @phillip, @billybobthorton We will like to know more from you on whether this fits your use case.