Search code examples
javascriptnode.jsreactjsapollo-serverprisma-graphql

How to make multiple connects in one GQL mutation?


So I have the following in my Prisma datamodel. There's a relationship between the games and the characters, where the characters can appear in multiple games. Also the characters should be able to be listed on the games when the games alone are queried:

type Game {
  id: ID! @unique
  name: String! @unique
  name_ja: String @unique
  name_ko: String @unique
  name_zh_CN: String @unique
  name_zh_TW: String @unique
  name_zh_HK: String @unique
  characters: [Character]
  filters: [GameFilter]
}

type Character {
  id: ID! @unique
  name: String! @unique
  name_ja: String @unique
  name_ko: String @unique
  name_zh_CN: String @unique
  name_zh_TW: String @unique
  name_zh_HK: String @unique
  games: [Game]
}

I then have this as a mutation for updating characters in my schema. I pass along an array of Game IDs because there's the possibility of multiple games being added within the same mutation:

updateCharacter(
        name: String
        name_ja: String
        name_ko: String
        name_zh_CN: String
        name_zh_HK: String
        name_zh_TW: String
        id: ID!
        games: [ID]
    ): Character!

And the following mutation written:

async updateCharacter(parent, args, ctx, info) {
        if (!ctx.request.userId) {
            throw new Error('You must be logged in');
        }

        const updates = {...args};

        delete updates.id;
        delete updates.games;

        console.log(args.games);

        const res = await ctx.db.mutation.updateCharacter({
            data: updates,
            games: {
                connect: {
                    id: args.games
                }
            },
            where: {
                id: args.id
            }
        }, info);
        return res;
    }

And the following mutation written React-side. It's meant to pass along an array of IDs to the mutation (which will be expected because the schema assumes that an array of IDs will be passed along:

const UPDATE_CHARACTER_MUTATION = gql`
    mutation UPDATE_CHARACTER_MUTATION(
        $name: String!
        $name_ja: String!
        $name_ko: String!
        $name_zh_CN: String!
        $name_zh_TW: String!
        $name_zh_HK: String!
        $id: ID!
        $games: [ID]!
    ) {
        updateCharacter(
            name: $name
            name_ja: $name_ja
            name_ko: $name_ko
            name_zh_CN: $name_zh_CN
            name_zh_TW: $name_zh_TW
            name_zh_HK: $name_zh_HK
            games: $games
            id: $id
        ) {
            id
            name
            name_ja
            name_ko
            name_zh_CN
            name_zh_TW
            name_zh_HK
            games {
                id
                name
            }
        }
    }
`;

I am also passing along the IDs of the games in an array onSubmit within the form to the mutation.

The result is that the mutation passes, but will only update the name fields, and the connection with the Games remains unchanged.

Not sure what I can do to make this mutate properly. I'm not sure whether passing the array directly into the mutation in the connect is what's causing the issue, but I tried mapping through and passing along each game id individually, but had the same result of the connection not updating.


Solution

  • The problem seems to be two-fold.

    Regarding not seeing any changes at all:

    In the mutation written, games is added to the async request json outside of data, meaning the data will never be found by the request. Rather than:

    data: ...,
    games: ...
    

    games must be part of data like such:

    data: {
      games: ...
    }
    

    Regarding wanting to do multiple connects:

    GraphQL supports this style of nested updates using the following connect syntax:

    connect: [
      { id : /* id from args */ },
      { id : /* another id from args */ },
      ...
    ]