Creating multiple nodes of the same type in a single mutation


#1

Is there any way i can create multiple nodes of the same type in a single mutation ie
I can do createAuthor on an author type but is there something like createAuthors to create multiple authors at once ?


Mutation: create multiple nodes - why error?
Query batching in Graphcool vs Apollo
#2

There is no createAuthors mutation available, but there are two ways to create multiple nodes in a single GraphQL document.

One option is to use a nested create mutation. For example, if your schema looks like this:

type Author {
  id: ID!
  name: String!
  group: Group @relation(name: "AuthorGroup")
}

type Group {
  id: ID!
  description: String!
  authors: [Author!]! @relation(name: "AuthorGroup")
}

you can create one group and create many connected authors at the same time:

mutation {
  createGroup(
    description: "A group of cool authors"
    authors: [{
      name: "Edgar Allan Poe"
    }. {
      name: "Arthur Conan Doyle"
    }]
  ) {
    id
    authors {
      id
    }
  }
}

Even if your schema doesn’t look like this, you can add a “dummy” type that’s analog to Group to create many authors at once.

Another option is to concatenate the strings for the separate createAuthor mutations into a single GraphQL document using GraphQL Aliases.

const createAuthor = (name) => {
  const alias = `alias_${Math.random().toString(36).slice(2)}`

  return `
    ${alias}: createAuthor(name: "${name}") {
      id
    }
  `
}

const createAuthors = (mutations) => {
  const joinedMutations = mutations.join('\n')
  
  return `
  mutation createAuthors {
    ${joinedMutations}
  }
  `
}

const mutations  = ["Edgar Allan Poe", "Arthur Conan Doyle"]
  .map(name => createAuthor(name))
const result = createAuthors(mutations)

You can then pass the result to a simple GraphQL client, for example graphql-request.

A script I recently wrote for a different use case can be used as comparison.


#3

Awesome. That helps a lot. Thanks!!


#4

Another question related to this: in option 1 that you suggested , you created a group and added authors. What if I wanted to add new authors to an existing group which already had a few authors belonging to it?


#5

That’s not possible in option 1 currently, that would be a nested append. You’d had to use option two and additionall add the groupId: ID! parameter in the createAuthor mutation to do a nested connect.


#6

Excellent! Thanks for sharing this script!


#7

If you concatenate separate mutations into a single document using aliases, do you get transactional guarantees? If one of the mutations fail for some reason, do all others fail?


#9

Hi @nilan

I’m pretty new in this stuff, so I’m trying to create a Medicine with many Alerts, my model looks like this:

Model

type Medicine {
    id: ID! @unique
    name: String!
    alerts: [Alert!]! @relation(name: "MedicineAlert")
}

type Alert {
    id: ID! @unique
    medicine: Medicine @relation(name: "MedicineAlert")
}

so I’m trying to figure out how my mutation should looks like in my schema.

Schema mutation

createMedicine(
    name: String!
    alerts: [_WHAT_SHOULD_BE_HERE_?]
): Medicine

Regards!


#10

All done!

I found between the generated inputs by Prisma there is one called AlertCreateManyWithoutMedicineInput and this works.

Now my model mutation looks lke this:

createMedicine(
    name: String!
    alerts: AlertCreateManyWithoutMedicineInput
): Medicine

and my mutation:

mutation createNewMedicine {
    createMedicine {
        name: "medicine title"
        alerts: {
           create: [{alertAt: 12312312}, {alertAt: 53453454}]
        }
    }
}