Search code examples
javascriptgraphqlmutationfaunadbgraphql-playground

When updating a record in FaunaDB, how do I update one field without passing in every field and subobject?


Perhaps I haven't grasped GraphQL yet, but I want to update a complex record in the DB. I'm having trouble finding docs that explain this, which doesn't use a trivial example. I am using FaunaDB and trying to test things in the GraphQL playground before implementing it in JS.

Here is an an example of my schema:

type Event {
    name: String!
    email: String!
    eventName: String!
    location: String
    guests: [Guest!]!
    note: String!
    confirmed: Boolean!
    completed: Boolean!
    dateTimeStart: Time
    dateTimeEnd: Time
    sentConfirmation: Boolean!
}

type Guest @embedded {
    email: String!
    rsvp: Boolean
    results: SurveyAnswers
}

type SurveyAnswers @embedded {
    ~ 12 various fields
}

I want to update a field on the event: sentConfirmation, that's it.

I know the event Id and what I want to update the Boolean value to.

Is there a way to write a mutation to just pass in an ID and the updated Boolean value and change that single value, or do I need to literally pass in the entire object and all it's sub objects with just that one top level field updated?


Solution

  • This should be possible by calling the autogenerated partialUpdate mutation. You might have not noticed it, since this is currently only available as a Schema Preview feature.

    This means essentially that in order to enable it, you will need to add the following header to your HTTP Request:

    X-Schema-Preview: partial-update-mutation
    

    Note that since this Schema Preview feature adds a new autogenerated mutation, you will have to add this header when executing a GraphQL operation (i.e., sending request against the /graphql endpoint), and not when importing the schema (i.e., sending a request agains the /import endpoint). The reason is basically that all of the autogenerated queries and mutations are derived at runtime, and not when the schema is imported.

    Now, if you have added the header as mentioned above, when calling some introspection query for reading the schema back (like the GraphQL Playground does for instance), you should notice there's a new mutation field and a new input object:

    input PartialUpdateEventInput {
      name: String
      email: String
      eventName: String
      location: String
      guests: [PartialUpdateGuestInput!]
      note: String
      confirmed: Boolean
      completed: Boolean
      dateTimeStart: Time
      dateTimeEnd: Time
      sentConfirmation: Boolean
    }
    
    type Mutation {
      partialUpdateEvent(id: ID!, data: PartialUpdateEventInput!): Event
    }
    

    Since all of the fields are optional for this new input object, you should be able now to update just the sentConfirmation field:

    mutation PartialUpdate {
      partialUpdateEvent(id: "269434161519919634", data: {
        sentConfirmation: true
      }) {
        _id
      }
    }
    

    All of the fields which are not included in the mutation will remain unaffected.

    Establishing a parallel with FQL, this means that GraphQL's update mutation will act as FQL's Replace function, and GraphQL's partialUpdate mutation as FQL's Update function.