### Install @neo4j/graphql Source: https://github.com/neo4j/graphql/blob/dev/packages/graphql/README.md Install the main package and its required peer dependencies. ```bash npm install @neo4j/graphql ``` ```bash npm install graphql neo4j-driver ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Installs all project dependencies using Yarn. Run this command from the root of the cloned repository. ```bash yarn install ``` -------------------------------- ### Quick Start with Apollo Server Source: https://github.com/neo4j/graphql/blob/dev/packages/graphql/README.md Initialize a Neo4jGraphQL instance with a schema and driver, then serve it via Apollo Server. ```javascript const { Neo4jGraphQL } = require("@neo4j/graphql"); const neo4j = require("neo4j-driver"); const { ApolloServer } = require("apollo-server"); const typeDefs = ` type Movie { title: String year: Int imdbRating: Float genres: [Genre!]! @relationship(type: "IN_GENRE", direction: OUT) } type Genre { name: String movies: [Movie!]! @relationship(type: "IN_GENRE", direction: IN) } `; const driver = neo4j.driver("bolt://localhost:7687", neo4j.auth.basic("neo4j", "letmein")); const neoSchema = new Neo4jGraphQL({ typeDefs, driver }); async function main() { const schema = await neoSchema.getSchema(); const server = new ApolloServer({ schema, context: ({ req }) => ({ req }), }); await server.listen(4000); console.log("Online"); } ``` -------------------------------- ### GraphQL Mutation Examples Source: https://github.com/neo4j/graphql/blob/dev/packages/graphql/README.md Examples of creating and connecting nodes using GraphQL mutations. ```graphql mutation { createMovies(input: [{ title: "The Matrix", year: 1999, imdbRating: 8.7 }]) { movies { title } } } ``` ```graphql mutation { updateMovies( where: { title: "The Matrix" } connect: { genres: { where: { node: { OR: [{ name: "Sci-fi" }, { name: "Action" }] } } } } ) { movies { title } } } ``` ```graphql mutation { createMovies( input: [ { title: "The Matrix" year: 1999 imdbRating: 8.7 genres: { connect: { where: { node: { AND: [{ name: "Sci-fi" }, { name: "Action" }] } } } } } ] ) { movies { title } } } ``` -------------------------------- ### Install @neo4j/graphql as Production Dependency Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Use this command to add the package for production use. ```bash yarn add @neo4j/graphql ``` -------------------------------- ### Install @neo4j/graphql as Test Dependency Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Use this command to add the package specifically for development and testing purposes. ```bash yarn add --dev @neo4j/graphql ``` -------------------------------- ### Install Yarn Globally Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Installs Yarn package manager globally using npm. Ensure Node.js is installed first. ```bash npm install -g yarn ``` -------------------------------- ### GraphQL Query Example Source: https://github.com/neo4j/graphql/blob/dev/packages/graphql/README.md Retrieve movies and their associated genres. ```graphql query { movies { title genres { name } } } ``` -------------------------------- ### Run Docker Compose Tests Source: https://github.com/neo4j/graphql/blob/dev/packages/apollo-federation-subgraph-compatibility/README.md Execute subgraph compatibility tests using Docker Compose. Ensure Docker is installed. ```bash yarn test:docker ``` -------------------------------- ### Point Data Type Query and Cypher Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Example of handling Point types in GraphQL queries and the corresponding Cypher translation. ```graphql type PointContainer { point: Point } ``` ```graphql { pointContainers(where: { point: { longitude: 1.0, latitude: 2.0 } }) { point { longitude latitude crs } } } ``` ```cypher MATCH (this:PointContainer) WHERE this.point = point($this_point) RETURN this { point: apoc.cypher.runFirstColumn('RETURN CASE WHEN this.point IS NOT NULL THEN { point: this.point, crs: this.point.crs } ELSE NULL END AS result',{ this: this },false) } as this ``` -------------------------------- ### Increase Schema Size for Benchmark Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Artificially increase the schema size for benchmarks by a factor specified with the `--schemaSize` option. For example, `--schemaSize 500` generates a schema roughly 500 times larger. ```bash yarn performance --schemaSize 500 ``` -------------------------------- ### Change Number of Translation Runs Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Customize the number of times each query is translated during the translation benchmark by using the `--runs` option. For example, to run 1000 times per query. ```bash yarn performance --translation --runs 1000 ``` -------------------------------- ### Run Package Tests Source: https://github.com/neo4j/graphql/blob/dev/packages/package-tests/README.md Navigate to the `packages/graphql` directory and execute this command to run the package tests. These tests verify the production build of the package. ```bash cd packages/graphql npm run test:package-tests ``` -------------------------------- ### Build and Run Load Tests Source: https://github.com/neo4j/graphql/blob/dev/packages/graphql/tests/performance/server/README.md Commands to build the package and execute performance testing utilities. ```bash yarn build ``` ```bash yarn doctor-yoga ``` ```bash yarn flame-yoga ``` ```bash yarn load ``` -------------------------------- ### Run Performance Benchmarks Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Executes performance benchmarks for the @neo4j/graphql package. Navigate to the packages/graphql directory and run this command. ```bash yarn performance ``` -------------------------------- ### Run Raw Cypher Queries for Performance Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Enable running raw Cypher queries for performance comparison by passing the `--cypher` flag. Cypher queries should be located in `tests/performance/databaseQuery/cypher`. ```bash yarn performance --cypher ``` -------------------------------- ### Manage Neo4j Session with beforeAll/afterAll Source: https://github.com/neo4j/graphql/wiki/Testing Open and close a Neo4j session once for the entire test file using `beforeAll` and `afterAll`. Prefer this if test data is shared across all tests. Use `Neo4j.getSession()` for session creation. ```typescript import type { Driver, Session } from "neo4j-driver"; import Neo4j from "./neo4j"; describe("This is a test file", () => { let neo4j: Neo4j; let driver: Driver; let session: Session; beforeAll(async () => { neo4j = new Neo4j(); driver = await neo4j.getDriver(); session = await neo4j.getSession(); }); afterAll(async () => { await session.close(); await driver.close(); }); }); ``` -------------------------------- ### Run TCK Test Suite Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Executes the TCK (Technology Compatibility Kit) test suite for @neo4j/graphql. Run this from the packages/graphql directory. ```bash yarn test:tck ``` -------------------------------- ### Run Subgraph Schema Generation Benchmark Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Execute the schema generation benchmark specifically for subgraph compatibility by using the `--subgraph-schema` flag. ```bash yarn performance --subgraph-schema ``` -------------------------------- ### Construct Neo4j Driver Instance Source: https://github.com/neo4j/graphql/wiki/Testing Instantiate a Neo4j driver in the `beforeAll` hook and close it in `afterAll`. Use the `Neo4j.getDriver()` helper for construction. ```typescript import type { Driver } from "neo4j-driver"; import Neo4j from "./neo4j"; describe("This is a test file", () => { let driver: Driver; beforeAll(async () => { neo4j = new Neo4j(); driver = await neo4j.getDriver(); }); afterAll(async () => { await driver.close(); }); }); ``` -------------------------------- ### Run Translation Benchmark Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Initiate the translation benchmark, which measures the time to translate GraphQL queries without database interaction, using the `--translation` flag. ```bash yarn performance --translation ``` -------------------------------- ### Generate Performance Benchmark Output in Markdown Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Format the database query benchmark output in markdown by using the `--markdown` option. This is only available for database query benchmarks. ```bash yarn performance --markdown ``` -------------------------------- ### Manage Neo4j Session with beforeEach/afterEach Source: https://github.com/neo4j/graphql/wiki/Testing Open and close a Neo4j session for each test using `beforeEach` and `afterEach`. This ensures test scope encapsulation. Use `Neo4j.getSession()` for session creation. ```typescript import type { Driver, Session } from "neo4j-driver"; import Neo4j from "./neo4j"; describe("This is a test file", () => { let neo4j: Neo4j; let driver: Driver; let session: Session; beforeAll(async () => { neo4j = new Neo4j(); driver = await neo4j.getDriver(); }); beforeEach(async () => { session = await neo4j.getSession(); }); afterAll(async () => { await session.close(); }); afterAll(async () => { await driver.close(); }); }); ``` -------------------------------- ### Run PM2 Tests Source: https://github.com/neo4j/graphql/blob/dev/packages/apollo-federation-subgraph-compatibility/README.md Execute subgraph compatibility tests using PM2. Requires PM2, Rover, and Neo4j. ```bash yarn test:pm2 ``` -------------------------------- ### Run Schema Generation Benchmark Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Execute the schema generation benchmark by running `yarn performance --schema`. This measures the time taken to generate a large GraphQL schema. ```bash yarn performance --schema ``` -------------------------------- ### Run All Tests with Custom Credentials Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Executes all project tests using Jest, specifying custom Neo4j connection details via environment variables. Ensure a Neo4j instance is running. ```bash NEO_URL=neo4j://localhost:7687 NEO_USER=neo4j NEO_PASSWORD=password yarn test ``` -------------------------------- ### Link Local Cypher-Builder Package Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Links a locally cloned Cypher-Builder package into the Neo4j GraphQL project. This allows testing changes in Cypher-Builder without publishing. ```bash yarn link -p [path-to-local-cypher-builder] ``` -------------------------------- ### Import Neo4jGraphQL Source: https://github.com/neo4j/graphql/blob/dev/packages/graphql/README.md Import the Neo4jGraphQL class using CommonJS syntax. ```javascript const { Neo4jGraphQL } = require("@neo4j/graphql"); ``` -------------------------------- ### Verify TCK Tests with Environment Variable Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Runs the TCK tests and verifies the generated Cypher. Set the VERIFY_TCK environment variable to true. ```bash VERIFY_TCK=true yarn test:tck ``` -------------------------------- ### Run Asynchronous Translation Runs Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Perform all translation runs for each test asynchronously using the `--async` flag. This can make tests faster and more representative of a real server but may affect result reliability. ```bash yarn performance --translation --async ``` -------------------------------- ### Clone Neo4j GraphQL Repository Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Clones the Neo4j GraphQL repository for browsing. For contributions, fork the repository first. ```bash https://github.com/neo4j/graphql.git ``` -------------------------------- ### Run Single Translation Per Query Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Execute each query translation only once during the translation benchmark by using the `--single` flag. This makes tests faster but less accurate. ```bash yarn performance --translation --single ``` -------------------------------- ### Shortest String Aggregation Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Demonstrates schema, query, and Cypher implementation for finding the shortest string in a collection. ```graphql type Movie { title: String! } ``` ```graphql { moviesAggregate { title { shortest } } } ``` ```cypher MATCH (this:Movie) RETURN { title: { shortest: reduce(shortest = collect(this.title)[0], current IN collect(this.title) | apoc.cypher.runFirstColumn(" RETURN CASE WHEN size(current) < size(shortest) THEN current ELSE shortest END AS result ", { current: current, shortest: shortest }, false)) } } ``` ```cypher MATCH (this:Movie) RETURN { title: { shortest: reduce(shortest = collect(this.title)[0], current IN collect(this.title) | CASE WHEN size(current) < size(shortest) THEN current ELSE shortest END ) }} as this ``` -------------------------------- ### Connection Projection Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Handles connection projections in mutations and queries. ```graphql type Actor { name: String movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT) } type Movie { title: String actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN) } ``` ```graphql mutation { createActors( input: { name: "Dan" movies: { connect: { where: { node: { title: "The Matrix" } } } } } ) { actors { name movies { actorsConnection(where: { node: { name: "Dan" } }) { totalCount edges { node { name } } } } } } } ``` ```cypher CALL { CREATE (this0:Actor) SET this0.name = "Dan" WITH this0 CALL { WITH this0 OPTIONAL MATCH (this0_movies_connect0_node:Movie) WHERE this0_movies_connect0_node.title = "The Matrix" FOREACH(_ IN CASE WHEN this0 IS NULL THEN [] ELSE [1] END | FOREACH(_ IN CASE WHEN this0_movies_connect0_node IS NULL THEN [] ELSE [1] END | MERGE (this0)-[:ACTED_IN]->(this0_movies_connect0_node) ) ) RETURN count(*) AS _ } RETURN this0 } RETURN [ this0 { .name, movies: [ (this0)-[:ACTED_IN]->(this0_movies:Movie) | this0_movies { actorsConnection: apoc.cypher.runFirstColumn("CALL { WITH this0_movies MATCH (this0_movies)<-[this0_movies_acted_in_relationship:ACTED_IN]-(this0_movies_actor:Actor) WHERE this0_movies_actor.name = \"Dan\" WITH collect({ node: { name: this0_movies_actor.name } }) AS edges UNWIND edges as edge RETURN { edges: collect(edge), totalCount: size(edges) } AS actorsConnection } RETURN actorsConnection", { this0_movies: this0_movies }, false) } ] }] AS data ``` -------------------------------- ### Environment Variables for Neo4j Connection Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Defines environment variables for connecting to a Neo4j database. These can be placed in a .env file in the repository root to be automatically picked up by Jest. ```env NEO_URL=neo4j://localhost:7687 NEO_USER=neo4j NEO_PASSWORD=password ``` -------------------------------- ### Configure tsconfig.json for Production Dependencies Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Update your project's tsconfig.json to include the @neo4j/graphql internal dependency. Ensure `baseUrl`, `paths`, and `references` are correctly set. ```json { "extends": "../../../tsconfig.base.json", "compilerOptions": { "baseUrl": "./", "outDir": "../dist", "paths": { "@neo4j/graphql": ["../../graphql/src"] } }, "references": [{ "path": "../../graphql/src/tsconfig.json" }] } ``` -------------------------------- ### Proposed Cypher for Actor Creation and Projection Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Demonstrates a complex Cypher structure for creating an actor and projecting related movie data. ```cypher CALL { CREATE (this0:Actor) SET this0.name = "Dan" WITH this0 CALL { WITH this0 OPTIONAL MATCH (this0_movies_connect0_node:Movie) WHERE this0_movies_connect0_node.title = "The Matrix" FOREACH(_ IN CASE WHEN this0 IS NULL THEN [] ELSE [1] END | FOREACH(_ IN CASE WHEN this0_movies_connect0_node IS NULL THEN [] ELSE [1] END | MERGE (this0)-[:ACTED_IN]->(this0_movies_connect0_node) ) ) RETURN count(*) AS _ } RETURN this0 } CALL { WITH this0 MATCH (this0)-[:ACTED_IN]->(this0_movies:Movie) WITH this0_movies MATCH (this0_movies)<-[this0_movies_acted_in_relationship:ACTED_IN]-(this0_movies_actor:Actor) WHERE this0_movies_actor.name = "Dan" WITH collect({ node: { name: this0_movies_actor.name } }) AS edges UNWIND edges as edge RETURN { edges: collect(edge), totalCount: size(edges) } AS actorsConnection } RETURN [ this0 { .name, movies: [{actorsConnection: actorsConnection }] AS data ``` -------------------------------- ### Introspect and persist GraphQL schema to file Source: https://github.com/neo4j/graphql/blob/dev/packages/introspector/README.md Generates GraphQL type definitions from a Neo4j database and writes them to a local file. ```js const { toGraphQLTypeDefs } = require("@neo4j/introspector"); const neo4j = require("neo4j-driver"); const fs = require("fs"); const driver = neo4j.driver("neo4j://localhost:7687", neo4j.auth.basic("neo4j", "password")); const sessionFactory = () => driver.session({ defaultAccessMode: neo4j.session.READ }); // We create a async function here until "top level await" has landed // so we can use async/await async function main() { const typeDefs = await toGraphQLTypeDefs(sessionFactory); fs.writeFileSync("schema.graphql", typeDefs); await driver.close(); } main(); ``` -------------------------------- ### Cypher Projection Implementation Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Cypher query using apoc.runFirstColumn for projecting the top actor within a Movie node. ```cypher MATCH (this:Movie) RETURN this { .title, topActor: head([this_topActor IN apoc.cypher.runFirstColumn("MATCH (a:Person) RETURN a", {this: this}, false) | this_topActor { .name }]) } as this ``` -------------------------------- ### Configure jest.config.js for Internal Dependencies Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Configure Jest to recognize the internal @neo4j/graphql dependency by specifying the correct tsconfig path in the `globals` section. ```javascript const globalConf = require("../../jest.config.base"); module.exports = { ...globalConf, displayName: "@neo4j/graphql-project", roots: ["/packages/project/src", "/packages/project/tests"], coverageDirectory: "/packages/project/coverage/", globals: { "ts-jest": { tsconfig: "/packages/project/src/tsconfig.json", }, }, }; ``` -------------------------------- ### Introspect and initialize read-only ApolloServer Source: https://github.com/neo4j/graphql/blob/dev/packages/introspector/README.md Generates a read-only GraphQL schema directly from the database and initializes an ApolloServer instance without persisting files. ```js import { ApolloServer } from "@apollo/server"; import { startStandaloneServer } from "@apollo/server/standalone"; import { Neo4jGraphQL } from "@neo4j/graphql"; import { toGraphQLTypeDefs } from "@neo4j/introspector"; import neo4j from "neo4j-driver"; const driver = neo4j.driver("neo4j://localhost:7687", neo4j.auth.basic("neo4j", "password")); const sessionFactory = () => driver.session({ defaultAccessMode: neo4j.session.READ }); // We create a async function here until "top level await" has landed // so we can use async/await async function main() { const readonly = true; // We don't want to expose mutations in this case const typeDefs = await toGraphQLTypeDefs(sessionFactory, readonly); const neoSchema = new Neo4jGraphQL({ typeDefs, driver }); const server = new ApolloServer({ schema: await neoSchema.getSchema(), }); await startStandaloneServer(server, { context: async ({ req }) => ({ req }), }); } main(); ``` -------------------------------- ### Cypher Resolver Implementation Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Cypher query using apoc.cypher.runFirstColumn to fetch all Person nodes and then return their names. ```cypher WITH apoc.cypher.runFirstColumn(" MATCH (a:Person) RETURN a ", {}, true) as x UNWIND x as this WITH this RETURN this { .name } AS this ``` -------------------------------- ### Run Specific GraphQL Performance Query Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Append `_only` to a GraphQL query file in `tests/performance/graphql` to run only that specific query during performance tests. ```graphql query SimpleUnionQuery_only { users { name liked { ... on Person { name } ... on Movie { title } } } } ``` -------------------------------- ### Aggregate Where Implementation Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Cypher query using apoc.cypher.runFirstColumn to filter posts based on the count of their likes. ```cypher MATCH (this:Post) WHERE apoc.cypher.runFirstColumn(" MATCH (this)<-[this_likesAggregate_edge:LIKES]-(this_likesAggregate_node:User) RETURN count(this_likesAggregate_node) = $this_likesAggregate_count ", { this: this, this_likesAggregate_count: $this_likesAggregate_count }, false ) RETURN this { .content } as this ``` -------------------------------- ### Execute Cypher with apoc.cypher.doIt Source: https://github.com/neo4j/graphql/wiki/Apoc-usage Used in `translateTopLevelCypher` for mutations to execute the mutation statement before projections. This procedure may be removed in favor of subqueries and could impact performance. ```cypher apoc.cypher.doIt(statement, parameters) ``` -------------------------------- ### Element Where Filtering with Interfaces Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Demonstrates filtering elements using interfaces and relationship connections in GraphQL and Cypher. ```graphql interface Production { id: ID title: String } type Movie implements Production { id: ID title: String actorCount: Int genres: [Genre!]! @relationship(type: "IN_GENRE", direction: OUT) } type Genre { name: String movies: [Production!]! @relationship(type: "IN_GENRE", direction: IN) } ``` ```graphql query Genres { genres { moviesConnection(where: { "node": { "_on": { "Movie": { "genresConnection_ALL": { "node": { "name": "Sci-fi" } } } } } }) { totalCount } } } ``` ```cypher MATCH (this:Genre) CALL { WITH this CALL { WITH this MATCH (this)<-[this_in_genre_relationship:IN_GENRE]-(this_Movie:Movie) WHERE apoc.cypher.runFirstColumn("RETURN exists((this_Movie)-[:IN_GENRE]->(:Genre)) AND all(this_Movie_Genre_map IN [(this_Movie)-[this_Movie_Genre_MovieGenresRelationship:IN_GENRE]->(this_Movie_Genre:Genre) | { node: this_Movie_Genre, relationship: this_Movie_Genre_MovieGenresRelationship } ] WHERE this_Movie_Genre_map.node.name = $this_moviesConnection.args.where.node._on.Movie.genresConnection.node.name )", { this_Movie: this_Movie, this_moviesConnection: $this_moviesConnection }) WITH { node: { __resolveType: "Movie" } } AS edge RETURN edge } WITH collect(edge) as edges RETURN { totalCount: size(edges) } AS moviesConnection } RETURN this { moviesConnection } as this ``` -------------------------------- ### Proposed Cypher for Point Projection Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage An optimized Cypher approach for projecting point data from a container. ```cypher MATCH(this:PointContainer) WITH this, CASE WHEN this.point IS NOT NULL THEN {point: this.point, crs: this.point.crs} ELSE NULL END AS this_point RETURN this {.name, point: this_point} as this ``` -------------------------------- ### Convert Date Format with apoc.date.convertFormat Source: https://github.com/neo4j/graphql/wiki/Apoc-usage Used for projecting dates into different formats. Consider JavaScript alternatives if needed. No known performance issues. ```cypher apoc.date.convertFormat(toString(${value}), "iso_zoned_date_time", "iso_offset_date_time") ``` -------------------------------- ### Clone Forked Neo4j GraphQL Repository (SSH) Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Clones a forked Neo4j GraphQL repository using SSH, typically for making contributions. Ensure your SSH keys are set up. ```bash git@github.com:USERNAME/graphql.git ``` -------------------------------- ### Cypher Resolver Query Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage GraphQL query to fetch the names of all people. ```graphql { allPeople { name } } ``` -------------------------------- ### Introspect schema to generic structure Source: https://github.com/neo4j/graphql/blob/dev/packages/introspector/README.md Retrieves the database schema as a generic data structure for custom transformation purposes. ```js import { toGenericStruct } from "@neo4j/introspector"; import neo4j from "neo4j-driver"; const driver = neo4j.driver("neo4j://localhost:7687", neo4j.auth.basic("neo4j", "password")); const sessionFactory = () => driver.session({ defaultAccessMode: neo4j.session.READ }); async function main() { const genericStruct = await toGenericStruct(sessionFactory); // Programmatically transform to what you need. } main(); ``` -------------------------------- ### Field Aggregations Projection Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Projects field aggregation subqueries through runFirstColumn. ```graphql type Movie { title: String actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN) } type Actor { name: String age: Int movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT) } ``` ```graphql query { movies { actorsAggregate { node { age { min max average sum } } } } } ``` ```cypher MATCH (this:Movie) RETURN this { actorsAggregate: { node: { age: head(apoc.cypher.runFirstColumn("MATCH (this)<-[r:ACTED_IN]-(n:Person) RETURN {min: min(n.age), max: max(n.age), average: avg(n.age), sum: sum(n.age)}", { this: this })) } } } as this ``` ```cypher MATCH (this:Movie) CALL { WITH this MATCH(this)<-[r:ACTED_IN]-(n:Person) RETURN {min: min(n.age), max: max(n.age), average: avg(n.age), sum: sum(n.age)} AS agg_data } WITH * RETURN this { actorsAggregate: { node: agg_data } } as this ``` -------------------------------- ### Validate Data with apoc.util.validatePredicate Source: https://github.com/neo4j/graphql/wiki/Apoc-usage Use `apoc.util.validatePredicate` for authentication and constraint enforcement. There is no direct Cypher alternative, and implementing validation in JavaScript within a transaction can increase complexity. ```cypher apoc.util.validatePredicate(predicate, message, parameters) ``` -------------------------------- ### Unlink Local Cypher-Builder Package Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Unlinks the locally linked Cypher-Builder package from the Neo4j GraphQL project. Run this command in the root of the graphql project. ```bash yarn unlink @neo4j/cypher-builder ``` -------------------------------- ### Add Upstream Remote Repository Source: https://github.com/neo4j/graphql/blob/dev/docs/contributing/DEVELOPING.md Adds the official Neo4j GraphQL repository as an upstream remote. This is useful for keeping your forked repository in sync. ```bash git remote add upstream git@github.com:neo4j/graphql.git ``` -------------------------------- ### Validate Data with apoc.util.validate Source: https://github.com/neo4j/graphql/wiki/Apoc-usage Use `apoc.util.validate` for authentication and constraint enforcement. There is no direct Cypher alternative, and implementing validation in JavaScript within a transaction can increase complexity. ```cypher apoc.util.validate(predicate, message, parameters) ``` -------------------------------- ### Authorization Rules Source: https://github.com/neo4j/graphql/blob/dev/packages/graphql/README.md Define authorization rules using the @auth directive for nested relationships, fields, and RBAC. ```graphql type User { id: ID! username: String! } type Post { id: ID! title: String! moderator: User @relationship(type: "MODERATES_POST", direction: IN) } extend type Post @auth(rules: [{ allow: [{ moderator: { id: "$jwt.sub" } }], operations: [UPDATE] }]) ``` ```graphql type User { id: ID! username: String! } extend type User { password: String! @auth(rules: [{ OR: [{ allow: { id: "$jwt.sub" } }, { roles: ["admin"] }] }]) } ``` ```graphql type Customer @auth(rules: [{ operations: [READ], roles: ["read:customer"] }]) { id: ID name: String password: String @auth(rules: [{ operations: [READ], roles: ["admin"] }]) } type Invoice @auth(rules: [{ operations: [READ], roles: ["read:invoice"] }]) { id: ID csv: String total: Int } ``` -------------------------------- ### Aggregate Where Schema Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Schema definition for User and Post types, with a Post type having a LIKES relationship. ```graphql type User { name: String! } type Post { content: String! likes: [User!]! @relationship(type: "LIKES", direction: IN) } ``` -------------------------------- ### Aggregate Where Query Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage GraphQL query to find posts where the number of likes is exactly 10. ```graphql { posts(where: { likesAggregate: { count: 10 } }) { content } } ``` -------------------------------- ### Field Aggregations Count Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Uses runInColumn for count values in field aggregations. ```graphql type Movie { title: String actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN) released: DateTime } type Actor { name: String age: Int movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT) } ``` ```graphql query { movies { title actorsAggregate { count } } } ``` ```cypher MATCH (this:Movie) RETURN this { .title, actorsAggregate: { count: head(apoc.cypher.runFirstColumn("MATCH (this)<-[r:ACTED_IN]-(n:Person) RETURN COUNT(n)", { this: this })) } } as this ``` ```cypher MATCH (this:Movie) CALL { WITH this MATCH (this)<-[r:ACTED_IN]-(n:Person) RETURN COUNT(n) as person_count } WITH * RETURN this { .title, actorsAggregate: { count: person_count } } as this ``` -------------------------------- ### Cypher Projection Query Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage GraphQL query to fetch movie titles and their top actors. ```graphql { movies { title topActor { name } } } ``` -------------------------------- ### Proposed Cypher for Projection (Non-functional) Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage An alternative, non-functional Cypher query structure for projection, intended to illustrate a different approach. ```cypher MATCH(m:Movie) CALL { WITH m WITH m as this MATCH (a:Person) RETURN a } WITH m, collect(a) as projection RETURN m {.title, topActor: head([this_topActor IN projection | this_topActor { .name }]) } ``` -------------------------------- ### Proposed Cypher for Element Where Filtering Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage An improved Cypher implementation for filtering elements that addresses parameter mapping issues. ```cypher MATCH (this:Genre) CALL { WITH this CALL { WITH this MATCH (this)<-[this_in_genre_relationship:IN_GENRE]-(this_Movie:Movie) WHERE exists((this_Movie)-[:IN_GENRE]->(:Genre)) and all(x IN [ (this_Movie)-[this_Movie_Genre_MovieGenresRelationship:IN_GENRE]->(this_Movie_Genre:Genre) | { node: this_Movie_Genre, relationship: this_Movie_Genre_MovieGenresRelationship } ] WHERE x.node.name = $this_moviesConnection.name ) WITH { node: { __resolveType: "Movie" } } AS edge RETURN edge } WITH collect(edge) as edges RETURN { totalCount: size(edges) } AS moviesConnection } RETURN this { moviesConnection } as this ``` -------------------------------- ### Cypher Resolver Schema Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Schema definition for Person and a Query type with a @cypher directive to fetch all people. ```graphql type Person { actorId: ID! name: String } type Query { allPeople: [Person] @cypher( statement: """ MATCH (a:Person) RETURN a """ ) } ``` -------------------------------- ### Proposed Cypher for Aggregate Where Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage An alternative Cypher query structure for aggregation filtering, using CALL and WHERE clause. ```cypher MATCH(this:Post) CALL { WITH this MATCH(this)<-[:LIKES]-(u:User) RETURN count(u) as agg_count } WITH * WHERE agg_count=10 RETURN m {.title} as this ``` -------------------------------- ### Cypher Projection Schema Source: https://github.com/neo4j/graphql/wiki/Apoc-runFirstColumn-usage Schema definition for a Movie type with a @cypher directive to fetch the top actor. ```graphql type Movie { id: ID title: String topActor: Actor @cypher( statement: """ MATCH (a:Person) RETURN a """ ) } type Actor { name: String } ``` -------------------------------- ### Assert Array Equality Ignoring Order with jest-extended Source: https://github.com/neo4j/graphql/wiki/Testing Use `toIncludeSameMembers` matcher from `jest-extended` to assert array values and length while ignoring element order, preventing test flakiness. ```typescript const array = [1, 2, 3]; // assume that we don't know the order here expect(array).toIncludeSameMembers([3, 2, 1]); ``` ```typescript const o = { nestedArray = [1, 2, 3], // assume that we don't know the order here }; expect(o).toEqual({ nestedArray: expect.toIncludeSameMembers([3, 2, 1]), }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.