Graphql partial update should not require us to put in the required fields

If you have the following schema:

type User {
  email: String! @unique
  firstName: String
}

notice that email is a required field.

If I run this mutation, which is basically saying update the firstName and leave the rest the same.

mutation {
  updateUser (
    id: "645364634663",
    data: {
      firstName: "April"
    }
  ) {
    email
  }
}

It will return with the following message:

{
  "data": null,
  "errors": [
    {
      "message": "Field 'UserInput.email' of required type 'String!' was not provided. (line 2, column 46):\n  updateUser(id: \"314963206304956488\", data: {firstName: \"April\"}) {\n                                             ^",
      "locations": [
        {
          "line": 2,
          "column": 46
        }
      ]
    }
  ]
}

it still wants me to add the email address even though it actually didn’t change.

Hi @aprilmintacpineda,

So, it’s important to keep in mind that GraphQL is, generally speaking, merely an API for accessing your data. And any queries used on it only know the data that’s been provided to them. So if you send a mutation to update a record, the API only knows the data that’s actually contained in that query. It doesn’t read the existing record first to store any existing data. In this case, all it knows is it’s being sent a mutation to update a User record; and User records have to have an email attribute. Since there’s no email contained in the query, the mutation fails.

That said, we do have a method for handling this case. It’s called partial-update-mutation and it can be set in the GraphQL Playground or in your GraphQL calls directly. Either way, you’ll set a custom X header called X-Schema-Preview. See the section in the docs for more details..

Once that’s set, you’ll have access to a partialUpdate<Type> mutation to handle cases like this. It would look like:

type Mutation {
  partialUpdateUser(id: ID!, data: PartialUpdateUserInput!): User
}

type PartialUpdateUserInput {
  email: String
  firstName: String
}

More details are available in the docs page on it.

Yes sure, but it doesn’t really make sense to put the fields you don’t want to change on the graphql request does it? I think it should be supported by default. When doing a create mutation, of course you have to provide the required fields, but when doing an update mutation, you should only provide the fields you want to change, like in this case, I only want to change the firstName, that should be a default behavior as it is in other graphql services. It’s the default behavior with AWS AppSync’s graphql and it make sense to be the default behavior here too.

You make a good point; I’m happy to pass these observations along to our Product team. Though since partialUpdate<Type> will eventually reach GA, I think it’s entirely possible we’ll continue supporting that as the preferred mechanism to handle partial updates. But again, I’ll pass this along for future consideration.

For the time being, please continue to use partialUpdate<Type> for any mutations that only need to update part of the record.

HI @aprilmintacpineda thanks for your input here. I’ve seen different APIs take different approaches to the issue of explicit vs implicit updates. However, it’s not likely that we’d change the semantics of the existing update, since the partial-update-mutation method will be GA’d in the near future and changing the semantics of the existing Update operation constitutes a backwards breaking change. I’d prefer that user not have to change their code to deal with.

Is the partial update supported out of the box, that is, I don’t need to manually put it on my schema.graphql for each of my collections, or do I still need to do that?

Even if you change the specs according to what I mentioned, no one has to change their code, if they use the partial-update-mutation feature, then they can stick with it if they want to, if they don’t and they provide all fields, it also doesn’t affect them. The only impact I can see it will have would be for future projects, which, they would choose the most logical one and just use what I mentioned here because that’s more convenient and easier as if you’re on boarding new devs that’s not familiar with fauna, they would most likely be familiar with what I mentioned here.