Getting started with subscriptions

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.

This guide shows how to start using subscription capabilities on a GraphQL server.

If you use Apollo Studio, make sure to select the graphql-ws implementation in the connection settings.

Subscriptions can listen to changes to the database, including changes unrelated to the GraphQL library.

Enable subscription capabilities

Neo4j GraphQL subscriptions rely on Neo4j Change Data Capture. Make sure to follow the steps described in the CDC Documentation to enable it in FULL mode for your Neo4j instance.

Before using subscriptions on a GraphQL server, you must enable them by passing the subscriptions feature to Neo4jGraphQL:

new Neo4jGraphQL({
    typeDefs,
    driver,
    features: {
        subscriptions: true
    },
});

Setting up an @apollo/server server

Then, the next step is to install the following dependencies:

npm i --save ws graphql-ws neo4j-driver @neo4j/graphql express @apollo/server body-parser cors

Add the following code to your index.js file to implement a simple @apollo/server server with subscriptions (for more options, see Apollo’s documentation):

import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import bodyParser from 'body-parser';
import cors from "cors";
import { createServer } from "http";
import neo4j from 'neo4j-driver';
import { Neo4jGraphQL } from '@neo4j/graphql';
import { WebSocketServer } from "ws";
import { useServer } from "graphql-ws/lib/use/ws";
import express from 'express';

const typeDefs = `
    type Movie @node {
        title: String
    }

    type Actor @node {
        name: String
    }
`;

const driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("username", "password"));

const neoSchema = new Neo4jGraphQL({
    typeDefs,
    driver,
    features: {
        subscriptions: true
    },
});

async function main() {
    // Apollo server setup with WebSockets
    const app = express();
    const httpServer = createServer(app);
    const wsServer = new WebSocketServer({
        server: httpServer,
        path: "/graphql",
    });

    // Neo4j schema
    const schema = await neoSchema.getSchema();

    const serverCleanup = useServer(
        {
            schema,
            context: (ctx) => {
                return ctx;
            },
        },
        wsServer
    );

    const server = new ApolloServer({
        schema,
        plugins: [
            ApolloServerPluginDrainHttpServer({
                httpServer
            }),
            {
                async serverWillStart() {
                    return Promise.resolve({
                        async drainServer() {
                            await serverCleanup.dispose();
                        },
                    });
                },
            },
        ],
    });
    await server.start();

    app.use(
        "/graphql",
        cors(),
        bodyParser.json(),
        expressMiddleware(server, {
            context: async ({ req }) => ({ req }),
        })
    );

    const PORT = 4000;
    httpServer.listen(PORT, () => {
        console.log(`Server is now running on http://localhost:${PORT}/graphql`);
    });
}

main();

GraphQL subscriptions

With the previous server running, the available subscriptions are set for Movie and Actor. You can subscribe to new movies created with the following statement:

subscription {
    movieCreated(where: { title_EQ: "The Matrix" }) {
        createdMovie {
            title
        }
    }
}

With that, any new movie created with the matching title will trigger a subscription. You can try this with the following query:

mutation {
    createMovies(input: [{ title_EQ: "The Matrix" }]) {
        movies {
            title
        }
    }
}