Create mutation generated by Neo4j GraphQL Library takes longer than expected

Hi there,

I've been working through the Getting Started guide for the Neo4j GraphQL Library and have a couple of questions.

The server I'm running is the code I pasted from the guide:

package.json

{
  "name": "neo4j-graphql-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@neo4j/graphql": "^3.2.0",
    "apollo-server": "^3.7.0",
    "graphql": "^16.5.0",
    "neo4j-driver": "^4.4.5"
  }
}

index.js

const { Neo4jGraphQL } = require("@neo4j/graphql");
const { ApolloServer, gql } = require("apollo-server");
const neo4j = require("neo4j-driver");

const typeDefs = gql`
    type Movie {
        title: String
        actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN)
    }

    type Actor {
        name: String
        movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT)
    }
`;

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

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

neoSchema.getSchema().then((schema) => {
    const server = new ApolloServer({
        schema,
    });

    server.listen().then(({ url }) => {
        console.log(`🚀 Server ready at ${url}`);
    });
})

1. Why does it take 5 seconds to create 200 nodes via GraphQL?

The above server auto generates the mutation createMovies: CreateMoviesMutationResponse! which takes input: [MovieCreateInput!]!. If I call it with 200 MovieCreateInputs it takes about 5 seconds. e.g.

input: MovieCreateInput array - finished after 5.32s

mutation {
  createMovies(
    input: [
        { title: "Guardians of the Galaxy" },
        { title: "Prometheus" },
        { title: "Split" },
        { title: "Sing" },
        { title: "Suicide Squad" },
        { title: "The Great Wall" },
        { title: "La La Land" },
        { title: "Mindhorn" },
        { title: "The Lost City of Z" },
        { title: "Passengers" },
        { title: "Fantastic Beasts and Where to Find Them" },
        { title: "Hidden Figures" },
        { title: "Rogue One" },
        { title: "Moana" },
        { title: "Colossal" },
        { title: "The Secret Life of Pets" },
        { title: "Hacksaw Ridge" },
        { title: "Jason Bourne" },
        { title: "Lion" },
        { title: "Arrival" },
        { title: "Gold" },
        { title: "Manchester by the Sea" },
        { title: "Hounds of Love" },
        { title: "Trolls" },
        { title: "Independence Day: Resurgence" },
        { title: "Paris pieds nus" },
        { title: "Bahubali: The Beginning" },
        { title: "Dead Awake" },
        { title: "Bad Moms" },
        { title: "Assassin's Creed" },
        { title: "Why Him?" },
        { title: "Nocturnal Animals" },
        { title: "X-Men: Apocalypse" },
        { title: "Deadpool" },
        { title: "Resident Evil: The Final Chapter" },
        { title: "Captain America: Civil War" },
        { title: "Interstellar" },
        { title: "Doctor Strange" },
        { title: "The Magnificent Seven" },
        { title: "5/25/1977" },
        { title: "Sausage Party" },
        { title: "Moonlight" },
        { title: "Don't Fuck in the Woods" },
        { title: "The Founder" },
        { title: "Lowriders" },
        { title: "Pirates of the Caribbean: On Stranger Tides" },
        { title: "Miss Sloane" },
        { title: "Fallen" },
        { title: "Star Trek Beyond" },
        { title: "The Last Face" },
        { title: "Star Wars: Episode VII - The Force Awakens" },
        { title: "Underworld: Blood Wars" },
        { title: "Mother's Day" },
        { title: "John Wick" },
        { title: "The Dark Knight" },
        { title: "Silence" },
        { title: "Don't Breathe" },
        { title: "Me Before You" },
        { title: "Their Finest" },
        { title: "Sully" },
        { title: "Batman v Superman: Dawn of Justice" },
        { title: "The Autopsy of Jane Doe" },
        { title: "The Girl on the Train" },
        { title: "Fifty Shades of Grey" },
        { title: "The Prestige" },
        { title: "Kingsman: The Secret Service" },
        { title: "Patriots Day" },
        { title: "Mad Max: Fury Road" },
        { title: "Wakefield" },
        { title: "Deepwater Horizon" },
        { title: "The Promise" },
        { title: "Allied" },
        { title: "A Monster Calls" },
        { title: "Collateral Beauty" },
        { title: "Zootopia" },
        { title: "Pirates of the Caribbean: At World's End" },
        { title: "The Avengers" },
        { title: "Inglourious Basterds" },
        { title: "Pirates of the Caribbean: Dead Man's Chest" },
        { title: "Ghostbusters" },
        { title: "Inception" },
        { title: "Captain Fantastic" },
        { title: "The Wolf of Wall Street" },
        { title: "Gone Girl" },
        { title: "Furious Seven" },
        { title: "Jurassic World" },
        { title: "Live by Night" },
        { title: "Avatar" },
        { title: "The Hateful Eight" },
        { title: "The Accountant" },
        { title: "Prisoners" },
        { title: "Warcraft" },
        { title: "The Help" },
        { title: "War Dogs" },
        { title: "Avengers: Age of Ultron" },
        { title: "The Nice Guys" },
        { title: "Kimi no na wa" },
        { title: "The Void" },
        { title: "Personal Shopper" },
        { title: "The Departed" },
        { title: "Legend" },
        { title: "Thor" },
        { title: "The Martian" },
        { title: "Contratiempo" },
        { title: "The Man from U.N.C.L.E." },
        { title: "Hell or High Water" },
        { title: "The Comedian" },
        { title: "The Legend of Tarzan" },
        { title: "All We Had" },
        { title: "Ex Machina" },
        { title: "The Belko Experiment" },
        { title: "12 Years a Slave" },
        { title: "The Bad Batch" },
        { title: "300" },
        { title: "Harry Potter and the Deathly Hallows: Part 2" },
        { title: "Office Christmas Party" },
        { title: "The Neon Demon" },
        { title: "Dangal" },
        { title: "10 Cloverfield Lane" },
        { title: "Finding Dory" },
        { title: "Miss Peregrine's Home for Peculiar Children" },
        { title: "Divergent" },
        { title: "Mike and Dave Need Wedding Dates" },
        { title: "Boyka: Undisputed IV" },
        { title: "The Dark Knight Rises" },
        { title: "The Jungle Book" },
        { title: "Transformers: Age of Extinction" },
        { title: "Nerve" },
        { title: "Mamma Mia!" },
        { title: "The Revenant" },
        { title: "Fences" },
        { title: "Into the Woods" },
        { title: "The Shallows" },
        { title: "Whiplash" },
        { title: "Furious 6" },
        { title: "The Place Beyond the Pines" },
        { title: "No Country for Old Men" },
        { title: "The Great Gatsby" },
        { title: "Shutter Island" },
        { title: "Brimstone" },
        { title: "Star Trek" },
        { title: "Diary of a Wimpy Kid" },
        { title: "The Big Short" },
        { title: "Room" },
        { title: "Django Unchained" },
        { title: "Ah-ga-ssi" },
        { title: "The Edge of Seventeen" },
        { title: "Watchmen" },
        { title: "Superbad" },
        { title: "Inferno" },
        { title: "The BFG" },
        { title: "The Hunger Games" },
        { title: "White Girl" },
        { title: "Sicario" },
        { title: "Twin Peaks: The Missing Pieces" },
        { title: "Aliens vs Predator - Requiem" },
        { title: "Pacific Rim" },
        { title: "Crazy, Stupid, Love." },
        { title: "Scott Pilgrim vs. the World" },
        { title: "Hot Fuzz" },
        { title: "Mine" },
        { title: "Free Fire" },
        { title: "X-Men: Days of Future Past" },
        { title: "Jack Reacher: Never Go Back" },
        { title: "Casino Royale" },
        { title: "Twilight" },
        { title: "Now You See Me 2" },
        { title: "Woman in Gold" },
        { title: "13 Hours" },
        { title: "Spectre" },
        { title: "Nightcrawler" },
        { title: "Kubo and the Two Strings" },
        { title: "Beyond the Gates" },
        { title: "Her" },
        { title: "Frozen" },
        { title: "Tomorrowland" },
        { title: "Dawn of the Planet of the Apes" },
        { title: "Tropic Thunder" },
        { title: "The Conjuring 2" },
        { title: "Ant-Man" },
        { title: "Bridget Jones's Baby" },
        { title: "The VVitch: A New-England Folktale" },
        { title: "Cinderella" },
        { title: "Realive" },
        { title: "Forushande" },
        { title: "Love" },
        { title: "Billy Lynn's Long Halftime Walk" },
        { title: "Crimson Peak" },
        { title: "Drive" },
        { title: "Trainwreck" },
        { title: "The Light Between Oceans" },
        { title: "Below Her Mouth" },
        { title: "Spotlight" },
        { title: "Morgan" },
        { title: "Warrior" },
        { title: "Captain America: The First Avenger" },
        { title: "Hacker" },
        { title: "Into the Wild" },
        { title: "The Imitation Game" },
        { title: "Central Intelligence" }
    ]
  ) {
    movies {
      title
    }
  }
}

But if I generate my own Cypher query to create 200 nodes:

manually generated Cypher ran in Neo4j browser

CREATE (n0:Movie { title: "Guardians of the Galaxy" }),
(n1:Movie { title: "Prometheus" }),
(n2:Movie { title: "Split" }),
(n3:Movie { title: "Sing" }),
(n4:Movie { title: "Suicide Squad" }),
(n5:Movie { title: "The Great Wall" }),
(n6:Movie { title: "La La Land" }),
(n7:Movie { title: "Mindhorn" }),
(n8:Movie { title: "The Lost City of Z" }),
(n9:Movie { title: "Passengers" }),
(n10:Movie { title: "Fantastic Beasts and Where to Find Them" }),
(n11:Movie { title: "Hidden Figures" }),
(n12:Movie { title: "Rogue One" }),
(n13:Movie { title: "Moana" }),
(n14:Movie { title: "Colossal" }),
(n15:Movie { title: "The Secret Life of Pets" }),
(n16:Movie { title: "Hacksaw Ridge" }),
(n17:Movie { title: "Jason Bourne" }),
(n18:Movie { title: "Lion" }),
(n19:Movie { title: "Arrival" }),
(n20:Movie { title: "Gold" }),
(n21:Movie { title: "Manchester by the Sea" }),
(n22:Movie { title: "Hounds of Love" }),
(n23:Movie { title: "Trolls" }),
(n24:Movie { title: "Independence Day: Resurgence" }),
(n25:Movie { title: "Paris pieds nus" }),
(n26:Movie { title: "Bahubali: The Beginning" }),
(n27:Movie { title: "Dead Awake" }),
(n28:Movie { title: "Bad Moms" }),
(n29:Movie { title: "Assassin's Creed" }),
(n30:Movie { title: "Why Him?" }),
(n31:Movie { title: "Nocturnal Animals" }),
(n32:Movie { title: "X-Men: Apocalypse" }),
(n33:Movie { title: "Deadpool" }),
(n34:Movie { title: "Resident Evil: The Final Chapter" }),
(n35:Movie { title: "Captain America: Civil War" }),
(n36:Movie { title: "Interstellar" }),
(n37:Movie { title: "Doctor Strange" }),
(n38:Movie { title: "The Magnificent Seven" }),
(n39:Movie { title: "5/25/1977" }),
(n40:Movie { title: "Sausage Party" }),
(n41:Movie { title: "Moonlight" }),
(n42:Movie { title: "Don't Fuck in the Woods" }),
(n43:Movie { title: "The Founder" }),
(n44:Movie { title: "Lowriders" }),
(n45:Movie { title: "Pirates of the Caribbean: On Stranger Tides" }),
(n46:Movie { title: "Miss Sloane" }),
(n47:Movie { title: "Fallen" }),
(n48:Movie { title: "Star Trek Beyond" }),
(n49:Movie { title: "The Last Face" }),
(n50:Movie { title: "Star Wars: Episode VII - The Force Awakens" }),
(n51:Movie { title: "Underworld: Blood Wars" }),
(n52:Movie { title: "Mother's Day" }),
(n53:Movie { title: "John Wick" }),
(n54:Movie { title: "The Dark Knight" }),
(n55:Movie { title: "Silence" }),
(n56:Movie { title: "Don't Breathe" }),
(n57:Movie { title: "Me Before You" }),
(n58:Movie { title: "Their Finest" }),
(n59:Movie { title: "Sully" }),
(n60:Movie { title: "Batman v Superman: Dawn of Justice" }),
(n61:Movie { title: "The Autopsy of Jane Doe" }),
(n62:Movie { title: "The Girl on the Train" }),
(n63:Movie { title: "Fifty Shades of Grey" }),
(n64:Movie { title: "The Prestige" }),
(n65:Movie { title: "Kingsman: The Secret Service" }),
(n66:Movie { title: "Patriots Day" }),
(n67:Movie { title: "Mad Max: Fury Road" }),
(n68:Movie { title: "Wakefield" }),
(n69:Movie { title: "Deepwater Horizon" }),
(n70:Movie { title: "The Promise" }),
(n71:Movie { title: "Allied" }),
(n72:Movie { title: "A Monster Calls" }),
(n73:Movie { title: "Collateral Beauty" }),
(n74:Movie { title: "Zootopia" }),
(n75:Movie { title: "Pirates of the Caribbean: At World's End" }),
(n76:Movie { title: "The Avengers" }),
(n77:Movie { title: "Inglourious Basterds" }),
(n78:Movie { title: "Pirates of the Caribbean: Dead Man's Chest" }),
(n79:Movie { title: "Ghostbusters" }),
(n80:Movie { title: "Inception" }),
(n81:Movie { title: "Captain Fantastic" }),
(n82:Movie { title: "The Wolf of Wall Street" }),
(n83:Movie { title: "Gone Girl" }),
(n84:Movie { title: "Furious Seven" }),
(n85:Movie { title: "Jurassic World" }),
(n86:Movie { title: "Live by Night" }),
(n87:Movie { title: "Avatar" }),
(n88:Movie { title: "The Hateful Eight" }),
(n89:Movie { title: "The Accountant" }),
(n90:Movie { title: "Prisoners" }),
(n91:Movie { title: "Warcraft" }),
(n92:Movie { title: "The Help" }),
(n93:Movie { title: "War Dogs" }),
(n94:Movie { title: "Avengers: Age of Ultron" }),
(n95:Movie { title: "The Nice Guys" }),
(n96:Movie { title: "Kimi no na wa" }),
(n97:Movie { title: "The Void" }),
(n98:Movie { title: "Personal Shopper" }),
(n99:Movie { title: "The Departed" }),
(n100:Movie { title: "Legend" }),
(n101:Movie { title: "Thor" }),
(n102:Movie { title: "The Martian" }),
(n103:Movie { title: "Contratiempo" }),
(n104:Movie { title: "The Man from U.N.C.L.E." }),
(n105:Movie { title: "Hell or High Water" }),
(n106:Movie { title: "The Comedian" }),
(n107:Movie { title: "The Legend of Tarzan" }),
(n108:Movie { title: "All We Had" }),
(n109:Movie { title: "Ex Machina" }),
(n110:Movie { title: "The Belko Experiment" }),
(n111:Movie { title: "12 Years a Slave" }),
(n112:Movie { title: "The Bad Batch" }),
(n113:Movie { title: "300" }),
(n114:Movie { title: "Harry Potter and the Deathly Hallows: Part 2" }),
(n115:Movie { title: "Office Christmas Party" }),
(n116:Movie { title: "The Neon Demon" }),
(n117:Movie { title: "Dangal" }),
(n118:Movie { title: "10 Cloverfield Lane" }),
(n119:Movie { title: "Finding Dory" }),
(n120:Movie { title: "Miss Peregrine's Home for Peculiar Children" }),
(n121:Movie { title: "Divergent" }),
(n122:Movie { title: "Mike and Dave Need Wedding Dates" }),
(n123:Movie { title: "Boyka: Undisputed IV" }),
(n124:Movie { title: "The Dark Knight Rises" }),
(n125:Movie { title: "The Jungle Book" }),
(n126:Movie { title: "Transformers: Age of Extinction" }),
(n127:Movie { title: "Nerve" }),
(n128:Movie { title: "Mamma Mia!" }),
(n129:Movie { title: "The Revenant" }),
(n130:Movie { title: "Fences" }),
(n131:Movie { title: "Into the Woods" }),
(n132:Movie { title: "The Shallows" }),
(n133:Movie { title: "Whiplash" }),
(n134:Movie { title: "Furious 6" }),
(n135:Movie { title: "The Place Beyond the Pines" }),
(n136:Movie { title: "No Country for Old Men" }),
(n137:Movie { title: "The Great Gatsby" }),
(n138:Movie { title: "Shutter Island" }),
(n139:Movie { title: "Brimstone" }),
(n140:Movie { title: "Star Trek" }),
(n141:Movie { title: "Diary of a Wimpy Kid" }),
(n142:Movie { title: "The Big Short" }),
(n143:Movie { title: "Room" }),
(n144:Movie { title: "Django Unchained" }),
(n145:Movie { title: "Ah-ga-ssi" }),
(n146:Movie { title: "The Edge of Seventeen" }),
(n147:Movie { title: "Watchmen" }),
(n148:Movie { title: "Superbad" }),
(n149:Movie { title: "Inferno" }),
(n150:Movie { title: "The BFG" }),
(n151:Movie { title: "The Hunger Games" }),
(n152:Movie { title: "White Girl" }),
(n153:Movie { title: "Sicario" }),
(n154:Movie { title: "Twin Peaks: The Missing Pieces" }),
(n155:Movie { title: "Aliens vs Predator - Requiem" }),
(n156:Movie { title: "Pacific Rim" }),
(n157:Movie { title: "Crazy, Stupid, Love." }),
(n158:Movie { title: "Scott Pilgrim vs. the World" }),
(n159:Movie { title: "Hot Fuzz" }),
(n160:Movie { title: "Mine" }),
(n161:Movie { title: "Free Fire" }),
(n162:Movie { title: "X-Men: Days of Future Past" }),
(n163:Movie { title: "Jack Reacher: Never Go Back" }),
(n164:Movie { title: "Casino Royale" }),
(n165:Movie { title: "Twilight" }),
(n166:Movie { title: "Now You See Me 2" }),
(n167:Movie { title: "Woman in Gold" }),
(n168:Movie { title: "13 Hours" }),
(n169:Movie { title: "Spectre" }),
(n170:Movie { title: "Nightcrawler" }),
(n171:Movie { title: "Kubo and the Two Strings" }),
(n172:Movie { title: "Beyond the Gates" }),
(n173:Movie { title: "Her" }),
(n174:Movie { title: "Frozen" }),
(n175:Movie { title: "Tomorrowland" }),
(n176:Movie { title: "Dawn of the Planet of the Apes" }),
(n177:Movie { title: "Tropic Thunder" }),
(n178:Movie { title: "The Conjuring 2" }),
(n179:Movie { title: "Ant-Man" }),
(n180:Movie { title: "Bridget Jones's Baby" }),
(n181:Movie { title: "The VVitch: A New-England Folktale" }),
(n182:Movie { title: "Cinderella" }),
(n183:Movie { title: "Realive" }),
(n184:Movie { title: "Forushande" }),
(n185:Movie { title: "Love" }),
(n186:Movie { title: "Billy Lynn's Long Halftime Walk" }),
(n187:Movie { title: "Crimson Peak" }),
(n188:Movie { title: "Drive" }),
(n189:Movie { title: "Trainwreck" }),
(n190:Movie { title: "The Light Between Oceans" }),
(n191:Movie { title: "Below Her Mouth" }),
(n192:Movie { title: "Spotlight" }),
(n193:Movie { title: "Morgan" }),
(n194:Movie { title: "Warrior" }),
(n195:Movie { title: "Captain America: The First Avenger" }),
(n196:Movie { title: "Hacker" }),
(n197:Movie { title: "Into the Wild" }),
(n198:Movie { title: "The Imitation Game" }),
(n199:Movie { title: "Central Intelligence" }) RETURN n0.title, n1.title, n2.title, n3.title, n4.title, n5.title, n6.title, n7.title, n8.title, n9.title, n10.title, n11.title, n12.title, n13.title, n14.title, n15.title, n16.title, n17.title, n18.title, n19.title, n20.title, n21.title, n22.title, n23.title, n24.title, n25.title, n26.title, n27.title, n28.title, n29.title, n30.title, n31.title, n32.title, n33.title, n34.title, n35.title, n36.title, n37.title, n38.title, n39.title, n40.title, n41.title, n42.title, n43.title, n44.title, n45.title, n46.title, n47.title, n48.title, n49.title, n50.title, n51.title, n52.title, n53.title, n54.title, n55.title, n56.title, n57.title, n58.title, n59.title, n60.title, n61.title, n62.title, n63.title, n64.title, n65.title, n66.title, n67.title, n68.title, n69.title, n70.title, n71.title, n72.title, n73.title, n74.title, n75.title, n76.title, n77.title, n78.title, n79.title, n80.title, n81.title, n82.title, n83.title, n84.title, n85.title, n86.title, n87.title, n88.title, n89.title, n90.title, n91.title, n92.title, n93.title, n94.title, n95.title, n96.title, n97.title, n98.title, n99.title, n100.title, n101.title, n102.title, n103.title, n104.title, n105.title, n106.title, n107.title, n108.title, n109.title, n110.title, n111.title, n112.title, n113.title, n114.title, n115.title, n116.title, n117.title, n118.title, n119.title, n120.title, n121.title, n122.title, n123.title, n124.title, n125.title, n126.title, n127.title, n128.title, n129.title, n130.title, n131.title, n132.title, n133.title, n134.title, n135.title, n136.title, n137.title, n138.title, n139.title, n140.title, n141.title, n142.title, n143.title, n144.title, n145.title, n146.title, n147.title, n148.title, n149.title, n150.title, n151.title, n152.title, n153.title, n154.title, n155.title, n156.title, n157.title, n158.title, n159.title, n160.title, n161.title, n162.title, n163.title, n164.title, n165.title, n166.title, n167.title, n168.title, n169.title, n170.title, n171.title, n172.title, n173.title, n174.title, n175.title, n176.title, n177.title, n178.title, n179.title, n180.title, n181.title, n182.title, n183.title, n184.title, n185.title, n186.title, n187.title, n188.title, n189.title, n190.title, n191.title, n192.title, n193.title, n194.title, n195.title, n196.title, n197.title, n198.title, n199.title

It runs in 0.2 seconds (Neo4j: Added 200 labels, created 200 nodes, set 200 properties, started streaming 1 records after 203 ms and completed after 206 ms).

Although I would expect the GraphQL to take longer than executing Cypher directly on the Neo4j DB, I don't understand why it takes that much longer? Is it expected that if I want to create multiple nodes at a time I should be writing my own resolver that generates and executes cypher code instead?

2. Why does the auto generated create mutation take an input array but the update mutation can't?

updateMovies: UpdateMoviesMutationResponse!
where: MovieWhere
update: MovieUpdateInput
connect: MovieConnectInput
disconnect: MovieDisconnectInput
create: MovieRelationInput
delete: MovieDeleteInput

I wondered why you can provide an input array to the create mutation but the auto generated update mutation for movies above doesn't seem to accept an array?

So if I wanted to send a few updates at the same time I would have to send each as a separate request (e.g. Promise.all(update1, update2, update3)) or write my own resolver that accepted an array and construct/execute the cypher against the DB myself?

I'm relatively new to GraphQL/Neo4j, any help much appreciated :slightly_smiling_face:

> Why does it take 5 seconds to create 200 nodes via GraphQL?

There have been some recent performance improvements in the Neo4j GraphQL Library that result in more efficient generated Cypher statements. I would give it a try using a recent version of the library and see if you notice any performance improvements.

> Why does the auto generated create mutation take an input array but the update mutation can't?

The update mutations expose nested operations which can result in several create/update operations as well as the where input which can apply to any nodes that match the given predicate (thus applying the update to multiple nodes). For these reasons, the generated Cypher statement can already be quite complex for a single "update", let alone multiple input statements.