# RFC: Upsert Mutations

**URL:** <https://discuss.dgraph.io/t/rfc-upsert-mutations/12736>\
**Category:** GraphQL\
**Tags:** rfc, area:graphql\
**Created:** [February 11, 2021, 7:37am UTC](https://discuss.dgraph.io/t/rfc-upsert-mutations/12736 "2021-02-11T07:37:29Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rajas](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/rajas/32/4393_2.png) [@rajas](https://discuss.dgraph.io/u/rajas)\
**Post date:** [February 11, 2021, 7:37am UTC](https://discuss.dgraph.io/t/rfc-upsert-mutations/12736/1 "2021-02-11T07:37:29Z")

</div>

## 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:

```auto
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:

1. Use `queryPerson` with appropriate filters to find out if a there exists `Person` with `id = "2"`
2. If there exists a Person with `id = "2"`, carry out an `updatePerson` mutation.
3. If there does not exist any such `Person`, create a new Person with `id = "2"` and set its name to `"New Name"` using `addPerson` 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:

1. [How to upsert using GraphQL?](http://discuss.hypermode.com/t/how-to-upsert-using-graphql/9931)
2. [GraphQL equivalient to Insert on Duplicate Key Update](http://discuss.hypermode.com/t/graphql-equivalient-to-insert-on-duplicate-key-update/9337)
3. [Converting update query to an upsert query](http://discuss.hypermode.com/t/converting-update-query-to-an-upsert-query/8626)
4. [Upsert in gql](http://discuss.hypermode.com/t/upsert-in-gql/11171)
5. [Upsert equivalent on dgraph](http://discuss.hypermode.com/t/upsert-equivalent-on-dgraph/10691)

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:

```auto
mutation{
    addPerson(input: [AddPersonInput!]!): AddPersonPayload
}

```

Proposed addPerson Mutation after adding `upsert` as input variable:

```auto
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:

```auto
addPerson(input: [{ "id": "2", name: "New Name" }] , upsert: True)

```

## Limitations

1. 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 with `upsert` set to `True` will only affect the root level nodes and will update the values (if already existing) at root level only.
2. Setting `upsert` value to `True` 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.

---

<div class="post-metadata">

**Author:** ![amaster507](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/amaster507/32/4123_2.png) [@amaster507](https://discuss.dgraph.io/u/amaster507)\
**Post date:** [February 11, 2021, 8:17am UTC](https://discuss.dgraph.io/t/rfc-upsert-mutations/12736/2 "2021-02-11T08:17:43Z")

</div>

I believe it does. @pbassham and I were just discussing this yesterday privately.

The deep limitation is expected right now and follows the way the deep mutations work right now across the board.

This will greatly help when using GraphQL to update data from a third party where we may already have partial data.

---

<div class="post-metadata">

**Author:** ![billybobthorton](https://avatars.discourse-cdn.com/v4/letter/b/dbc845/32.png) [@billybobthorton](https://discuss.dgraph.io/u/billybobthorton)\
**Post date:** [February 11, 2021, 2:12pm UTC](https://discuss.dgraph.io/t/rfc-upsert-mutations/12736/3 "2021-02-11T14:12:02Z")

</div>

My needs are more around the need to do a group of transactions atomically. While I think it is a good improvement, it doesn’t affect me as much.

---

<div class="post-metadata">

**Author:** ![rajas](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/rajas/32/4393_2.png) [@rajas](https://discuss.dgraph.io/u/rajas)\
**Post date:** [February 25, 2021, 5:55pm UTC](https://discuss.dgraph.io/t/rfc-upsert-mutations/12736/4 "2021-02-25T17:55:50Z")

</div>

This feature has been implemented and has been merged to master, [https://github.com/dgraph-io/dgraph/pull/7433](https://github.com/dgraph-io/dgraph/pull/7433) . It will be a part of 21.03 release.

---

<div class="post-metadata">

**Author:** ![iyinoluwaayoola](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/iyinoluwaayoola/32/4282_2.png) [@iyinoluwaayoola](https://discuss.dgraph.io/u/iyinoluwaayoola)\
**Post date:** [March 11, 2021, 12:34am UTC](https://discuss.dgraph.io/t/rfc-upsert-mutations/12736/5 "2021-03-11T00:34:43Z")

</div>

@rajas Thanks for picking this up. For my understanding, why can’t the nested nodes be updated as well? That can save a lot of update requests especially when the data source is in that format (ie., JSON). In that case, I’ll expect upsert to also affect nested nodes and the upsert parameter is propagated across all transactions.

---

<div class="post-metadata">

**Author:** ![rajas](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/rajas/32/4393_2.png) [@rajas](https://discuss.dgraph.io/u/rajas)\
**Post date:** [March 11, 2021, 6:35am UTC](https://discuss.dgraph.io/t/rfc-upsert-mutations/12736/6 "2021-03-11T06:35:10Z")

</div>

Hi @iyinoluwaayoola,

> [@iyinoluwaayoola](#):
>
> why can’t the nested nodes be updated as well?

We wanted to mimic the behaviour of `Update Mutations` when the node exists in case of `Upsert` . It is not possible to update nested nodes but it is possible to add new nested nodes (just like Update does).

> [@iyinoluwaayoola](#):
>
> That can save a lot of update requests especially when the data source is in that format (ie., JSON). In that case, I’ll expect upsert to also affect nested nodes and the upsert parameter is propagated across all transactions.

Yes, this is true. We would also be adding support for nested level upserts as well at a later time. We plan to have an `upsert` variable at each nested level to allow this to happen. This will also offer more flexibility to Users.
