Selection Set

This is a GraphQL specific term. When you execute a query, you have the operation:

query {
    myOperation
}

And you also have a selection set. For example, from the example below:

query {
    myOperation {
        field1
        field2
    }
}

The following snippet is the selection set:

{
    field1
    field2
}

When using the OGM, you do not have to provide a selection set by default. Doing so would make using the OGM feel more like querying the GraphQL schema directly, when the OGM is designed as an abstraction over it. This is achieved by automatically generated basic selection sets. Given the following type definition:

type Movie {
    id: ID
    name: String
    genres: [Genre!]! @relationship(type: "IN_GENRE", direction: OUT)
    customCypher: String! @cypher(statement: "RETURN someCustomData")
}

type Genre {
    name: String
}

Neither relationship fields nor custom Cypher fields are included in the generated selection set, as they could be computationally expensive. So, given the type definition above, the generated selection set would be:

{
    id
    name
}

This means that by default, querying for Node(s), you would only get the .id and .name properties returned. If you want to select more fields, you can either define a selection set at execution time or as a static on the Model, as described below.

Selection set at execution time

Using this approach, you would pass in a selection set every time you interact with the OGM. This would be an appropriate approach if the selection set is going to be different every time you ask for data. A full example of this would be as follows:

const { OGM } = require("@neo4j/graphql-ogm")
const neo4j = require("neo4j-driver");

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

const typeDefs = `
    type Movie {
        id: ID
        name: String
        genres: [Genre!]! @relationship(type: "IN_GENRE", direction: OUT)
        customCypher: String! @cypher(statement: "RETURN someCustomData")
    }

    type Genre {
        name: String
    }
`;

const ogm = new OGM({ typeDefs, driver });
const Movie = ogm.model("Movie");

const selectionSet = `
    {
        id
        name
        genres {
            name
        }
        customCypher
    }
`;

ogm.init().then(() => {
    Movie.find({ selectionSet }).then((movies) => {
        // work with movies
    })
});

Note that the argument selectionSet is passed every invocation of the Movie.find() function.

Selection set as a static

Using this approach, you can assign a selection set to a particular Model, so that whenever it is queried, it will always return those fields. This is useful if the default selection set doesn’t quite give you enough data, but you don’t need the selection set to be dynamic on each request. See a full example below:

const { OGM } = require("@neo4j/graphql-ogm")
const neo4j = require("neo4j-driver");

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

const typeDefs = `
    type Movie {
        id: ID
        name: String
        genres: [Genre!]! @relationship(type: "IN_GENRE", direction: OUT)
        customCypher: String! @cypher(statement: "RETURN someCustomData")
    }

    type Genre {
        name: String
    }
`;

const ogm = new OGM({ typeDefs, driver });
const Movie = ogm.model("Movie");

const selectionSet = `
    {
        id
        name
        genres {
            name
        }
        customCypher
    }
`;

Movie.selectionSet = selectionSet;

ogm.init().then(() => {
    Movie.find().then((movies) => {
        // work with movies
    })
});

Note that despite not passing this selection set into Movie.find(), the requested fields will be returned on each request.