Mutations

Mutations for create, update and delete operations are automatically generated for each type defined in type definitions.

This section will briefly go through each Mutation generated, using the following type definitions as an example:

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)
}

A note on nested Mutations

You will see some basic examples of nested Mutations below, which barely scratch the surface of what can be achieved with them. We really encourage you to explore the power of what you can do with them!

However, it has to be noted that in order to provide the abstractions available in these Mutations, the output Cypher can end up being extremely complex, which can result in your database throwing out-of-memory errors depending on its configuration.

If out-of-memory errors are a regular occurrence, you can adjust the dbms.memory.heap.max_size parameter in the DBMS settings.

If you need to perform major data migrations, it may be best to manually write the necessary Cypher and execute this directly in the database.

1. Create

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

type CreatePostsMutationResponse {
    posts: [Post!]!
}

type CreateUsersMutationResponse {
    users: [User!]!
}

type Mutation {
    createPosts(input: [PostCreateInput!]!): CreatePostsMutationResponse!
    createUsers(input: [UsersCreateInput!]!): CreateUsersMutationResponse!
}

The CreateInput types closely mirror the object type definitions, allowing you to create not only the type in question, but to recurse down and perform further operations on related types in the same Mutation.

The id field will be absent from both create input types as the @id directive has been used.

1.1. Single create

A single user can be created by executing the following GraphQL statement:

mutation {
    createUsers(input: [
        {
            name: "John Doe"
        }
    ]) {
        users {
            id
            name
        }
    }
}

This will create a User with name "John Doe", and that name plus the autogenerated ID will be returned.

1.2. Nested create

A User and an initial Post can be created by executing the following:

mutation {
    createUsers(input: [
        {
            name: "John Doe"
            posts: {
                create: [
                    {
                        content: "Hi, my name is John!"
                    }
                ]
            }
        }
    ]) {
        users {
            id
            name
            posts {
                id
                content
            }
        }
    }
}

This will create a User with name "John Doe", an introductory Post, both of which will be returned with their autogenerated IDs.

2. Update

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.

2.1. Single update

Say we 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
        }
    }
}

2.2. Nested update

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: [
                { content: "An interesting way of adding a new Post!" }
            ]
        }
    ) {
        users {
            id
            name
            posts {
                content
            }
        }
    }
}

3. Delete

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

type DeleteInfo {
    nodesDeleted: Int!
    relationshipsDeleted: Int!
}

type Mutation {
    deletePosts(where: PostWhere, delete: PostDeleteInput): DeleteInfo!
    deleteUsers(where: UserWhere, delete: UserDeleteInput): DeleteInfo!
}

Note that the DeleteInfo type is the common return type for all delete Mutations.

3.1. Single Delete

A single post can be deleted by executing the following GraphQL statement:

mutation {
    deletePosts(where: [
        {
            id: "6042E807-47AE-4857-B7FE-1AADF522DE8B"
        }
    ]) {
        nodesDeleted
        relationshipsDeleted
    }
}

This will delete the post using the autogenerated ID that would have been returned after that post’s creation.

We would see that nodesDeleted would equal 1 (the post) and relationshipsDeleted would also equal equal 1 (the HAS_POST relationship between the Post and its author).

3.2. Nested Delete

Say that if when we delete a User, we want to delete all of their Posts as well. This can be achieved using a single nested delete operations:

mutation {
    deleteUsers(
        where: [
            {
                name: "Jane Doe"
            }
        ],
        delete: {
            posts: [
                where: { }
            ]
        }
    ) {
        nodesDeleted
        relationshipsDeleted
    }
}

You may look at that empty where argument and wonder what that’s doing. By the time we reach that argument, we are already only dealing with the posts that were created by Jane Doe, as we traversed the graph to those Post nodes from her User node. Essentially, the above query is equivalent to:

mutation {
    deleteUsers(
        where: [
            {
                name: "Jane Doe"
            }
        ],
        delete: {
            posts: [
                where: {
                    creator: {
                        name: "Jane Doe"
                    }
                }
            ]
        }
    ) {
        nodesDeleted
        relationshipsDeleted
    }
}

Slightly easier to reason with, but the output Cypher statement will have a redundant WHERE clause!