Update

Using the following type definitions for these examples:

type Post {
    id: ID! @id
    content: String!
    creator: User! @relationship(type: "HAS_POST", direction: IN)
}

type User {
    id: ID! @id
    name: String
    posts: [Post!]! @relationship(type: "HAS_POST", direction: OUT)
}

The following update Mutations and response types will be generated for the above type definitions:

type UpdatePostsMutationResponse {
    posts: [Post!]!
}

type UpdateUsersMutationResponse {
    users: [User!]!
}

type Mutation {
    updatePosts(
        where: PostWhere
        update: PostUpdateInput
        connect: PostConnectInput
        disconnect: PostDisconnectInput
        create: PostCreateInput
        delete: PostDeleteInput
    ): UpdatePostsMutationResponse!
    updateUsers(
        where: UserWhere
        update: UserUpdateInput
        connect: UserConnectInput
        disconnect: UserDisconnectInput
        create: UserCreateInput
        delete: UserDeleteInput
    ): UpdateUsersMutationResponse!
}

The id field not be update-able as the @id directive has been used.

Single update

Say you wanted to edit the content of a Post:

mutation {
    updatePosts(
        where: {
            id: "892CC104-A228-4BB3-8640-6ADC9F2C2A5F"
        }
        update: {
            content: "Some new content for this Post!"
        }
    ) {
        posts {
            content
        }
    }
}

Nested create

Instead of creating a Post and connecting it to a User, you could update a User and create a Post as part of the Mutation:

mutation {
    updateUsers(
        where: { name: "John Doe" }
        create: {
            posts: [
                { node: { content: "An interesting way of adding a new Post!" } }
            ]
        }
    ) {
        users {
            id
            name
            posts {
                content
            }
        }
    }
}

connectOrCreate relationships

If a related node has a @unique or @id directive defined, connectOrCreate can be used in a nested update to perform a MERGE operation on the related node, creating a new relationship and the related node if it doesn’t exist.

Consider the following type definitions:

type Actor {
    name: String!
    movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
}

type Movie {
    title: String
    id: ID! @id
    actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN)
}

Because a movie ID is unique, connectOrCreate can be used in an Actor mutation to ensure a movie exists before connecting. Note that only @unique or @id fields can be used in where:

mutation {
  updateActors(
    update: {
        movies: {
          connectOrCreate: {
            where: { node: { id: "1234" } }
            onCreate: { node: { title: "Forrest Gump" } }
          }
        }
    },
    where: { name: "Tom Hanks" }
  ) {
    info {
      nodesCreated
    }
  }
}

In this case, all actors matching "Tom Hanks" will be connected to the Movie with id "1234". If the movie with given ID does not exist, it will be created with the title "Forrest Gump".

For update operations, connectOrCreate can also be used as a top-level input:

mutation {
  updateActors(
      connectOrCreate: {
        movies: {
            where: { node: { id: "1234" } }
            onCreate: { node: { title: "Forrest Gump" } }
        }
      },
      where: { name: "Tom Hanks" }
  ) {
    info {
      nodesCreated
    }
  }
}

This operation is equivalent to the previous example.