Type Definitions

This page will walk through what needs to change in your type definitions before you can pass them into @neo4j/graphql.


Both neo4j-graphql-js and @neo4j/graphql are highly driven by GraphQL directives. Each heading in this section will address how/if one or many directives available in neo4j-graphql-js can be migrated to @neo4j/graphql.


Migrating this directive is trivial:

  1. Rename @relation to @relationship

  2. Rename the argument name to type

For example, @relation(name: "ACTED_IN", direction: OUT) becomes @relationship(type: "ACTED_IN", direction: OUT).

See Relationships for more information on relationships in @neo4j/graphql.

Relationship Properties

If for instance using neo4j-graphql-js, you have the following type definitions defining an ACTED_IN relationship with a roles property:

type Actor {
    movies: [ActedIn!]!

type Movie {
    actors: [ActedIn!]!

type ActedIn @relation(name: "ACTED_IN") {
    from: Actor
    to: Movie
    roles: [String!]

This will need to be refactored to the following in the new library:

type Actor {
    movies: [Movie!]! @relationship(type: "ACTED_IN", properties: "ActedIn", direction: OUT)

type Movie {
    actors: [Actor!]! @relationship(type: "ACTED_IN", properties: "ActedIn", direction: IN)

interface ActedIn @relationshipProperties {
    roles: [String!]

Note the following changes to the ActedIn type:

  • Changed from type to interface

  • Removed @relation directive

  • Removed from and to fields

And note the following changes to the two node types:

  • Relationship field types changed from the relationship type to the neighbouring node type

  • Normal @relationship directive added to each relationship field, with an additional properties argument pointing to the relationship properties interface


No change. See @cypher directive for more details on this directive in @neo4j/graphql.


@neo4j/graphql offers two directives for skipping autogeneration for specified types/fields:

  • @exclude: Skip generation of specified Query/Mutation fields for an object type

  • @computed: Ignore a field, which will need custom logic for resolution

@isAuthenticated, @hasRole and @hasScope

Will require significant migration, but will be worth the effort! See Auth.


Not supported at this time.


There is an equivalent directive in the new library, but it does not work using database constraints as per the old library. See @id.

These all relate to database indexes and constraints, which are not currently supported by @neo4j/graphql.


Scalar Types

Supported as you would expect, with additional BigInt support for 64 bit integers.

Temporal Types (DateTime, Date)

Temporal Types have been massively simplified in @neo4j/graphql, down to DateTime and Date, which use ISO 8601 and "yyyy-mm-dd" strings respectively for parsing and serialization.

In terms of migrating from the old library, the formatted field of the old DateTime type now becomes the value itself. For example, used in a query:

  Movie(released: { formatted: "1992-10-09T00:00:00Z" }) {

Has become:

  Movie(released: "1992-10-09T00:00:00Z") {

Due to the move to ISO 8601 strings, input types are no longer necessary for temporal instances, so _Neo4jDateTimeInput has become DateTime and _Neo4jDateInput has become Date for input.

Spatial Types

The single type in neo4j-graphql-js, Point, has been split out into two types:

Correspondingly, _Neo4jPointInput has also been split out into two input types:

  • PointInput

  • CartesianPointInput

Using them in Queries and Mutations should feel remarkably similar.

Interface Types

Supported, queryable using inline fragments as per neo4j-graphql-js, but can also be created using Nested Mutations. See Interfaces.

Union Types

Supported, queryable using inline fragments as per neo4j-graphql-js, but can also be created using Nested Mutations. See Unions.



An _id field exposing the underlying node ID is not included in each type by default in @neo4j/graphql like it was in neo4j-graphql-js. If you require this functionality (however, it should be noted that underlying node IDs should not be relied on because they can be reused), you can include a field definition such as in the following type definition:

type ExampleType {
  _id: ID! @cypher(statement: "RETURN ID(this)")