Custom Resolvers

The library will autogenerate Query and Mutation resolvers, so you don’t need to implement those resolvers yourself. However, if you would like additional behaviours besides the autogenerated CRUD operations, you can specify custom resolvers for these scenarios.

Custom object type field resolver

If you would like to add a field to an object type which is resolved from existing values in the type, rather than storing new values, you should mark it with the @computed directive (see below) and define a custom resolver for it. Take for instance a simple schema:

const typeDefs = `
    type User {
        firstName: String!
        lastName: String!
        fullName: String! @computed(from: ["firstName", "lastName"])
    }
`;

const resolvers = {
    User: {
        fullName(source) {
            return `${source.firstName} ${source.lastName}`;
        },
    },
};

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    resolvers,
});

Here fullName is a computed value from the fields firstName and lastName. Specifying the @computed directive on the field definition keeps fullName from being included in any Query or Mutation fields and hence as a property on the :User node in the database.

The inclusion of the fields firstName and lastName in the from argument means that in the definition of the resolver the properties firstName and lastName will always be defined on the source object. If these fields are not specified, this cannot be guaranteed.

@computed

This field will essentially be completely ignored during the generation of Query and Mutation fields, and will require another way to resolve the field, such as through the use of a custom resolver.

Any fields that the custom resolver depends on should be passed to the from argument to ensure that during the Cypher generation process those properties are selected from the database. Allowable fields are any returning a Scalar or Enum type including those defined using the @cypher directive.

Definition

"""Informs @neo4j/graphql that a field will be resolved by a custom resolver, and allows specification of any field dependencies."""
directive @computed(
    """Fields that the custom resolver will depend on."""
    from: [String!]
) on FIELD_DEFINITION

Custom Query/Mutation type field resolver

You can define additional custom Query and Mutation fields in your type definitions and provide custom resolvers for them. A prime use case for this is using the OGM to manipulate types and fields which are not available through the API. You can find an example of it being used in this capacity in the Custom Resolvers example.