create

This is the documentation of the GraphQL Library version 6. For the long-term support (LTS) version 5, refer to GraphQL Library version 5 LTS.

Consider the following type definitions:

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

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

The following create mutations and response types are generated:

type CreatePostsMutationResponse {
    posts: [Post!]!
}

type CreateUsersMutationResponse {
    users: [User!]!
}

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

Note that the CreateInput types closely mirror the object type definitions. This allows 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 is absent from both create input types as the @id directive has been used.

Single create

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

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

This creates a User with the name "John Doe". The name and the autogenerated ID are returned.

Nested create

You can create a User and their initial Post at once by executing the following:

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

This creates a User with name "John Doe" and an introductory post. Both are returned with their autogenerated IDs.

You can perform similar and complementary actions by using the update mutation combined with create. Read about update for more information.

connectOrCreate relationships

If a related node has the @unique directive defined, you can use connectOrCreate nested in a create mutation to perform an operation similar to a Cypher MERGE operation on the related node. This will create a new relationship and the related node if it doesn’t exist yet.

Consider the following type definitions:

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

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

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

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

This ensures that a movie with ID 1234 exists and is connected to "Tom Hanks". If the movie does not exist, it will be created with the title "Forrest Gump". If a movie with the given ID already exists, it will also be connected to "Tom Hanks", and keep whatever title it has.

create optimization

With create operations, there is no limit on how many nodes can be created at once. However, there is a known performance issue for large batch sizes.

The Neo4j GraphQL Library contains an optimization feature designed to mitigate it, but it does not work in the following scenarios:

  • A field is populated using the directive @populated_by.

  • The connect or connectOrCreate operations are used.

  • Interface and union types are present in the mutation.