Update many from the one side of 1-M relationship

prisma

#1

My issue looks similar to Apollo Client: Update Mutation Error except that @Gabriel_Bravo says that it works from the Playground. I get the error in the playground, haven’t tried from the client. I’m posting this issue with more data on my environment in hopes that may be useful.

What I’m trying to accomplish:

One Folder type has many Item types.

A folder’s Items list exists in the order Items are added to the Folder. There is no field defining the order for Items in the Folder’s items list.

I am hoping to edit Items as a client-side array, to add, remove or re-order them, and submit the modified array to a mutation that will update the Folder’s items field to reflect the changes.

If I don’t provide an $items variable I can update $state or $name as expected.

When I attempt to update $items, I get an error

Field \"0\" is not defined by type ItemUpdateManyWithoutFolderInput at value.items.

While the error makes sense, I have no idea what I have to do to provide the missing definition.

Perhaps what I’m trying to do is just wrong, perhaps I’ve missed something simple?

Any help would be appreciated! :grinning:

Versions:
$ prisma -v prisma/1.5.3 (darwin-x64) node-v8.11.1

Here’s the full error as shown in the Playground:

      "data": null,
      "errors": [
        {
          "message": "Variable \"$_data\" got invalid value {\"items\":[{\"id\":\"cjelswuq3000z0102tsiefn4k\",\"title\":\"meh\"},{\"id\":\"cjelsy06f001601022ezfalu2\",\"title\":\"amazon\"}]}; Field \"0\" is not defined by type ItemUpdateManyWithoutFolderInput at value.items.\nVariable \"$_data\" got invalid value {\"items\":[{\"id\":\"cjelswuq3000z0102tsiefn4k\",\"title\":\"meh\"},{\"id\":\"cjelsy06f001601022ezfalu2\",\"title\":\"amazon\"}]}; Field \"1\" is not defined by type ItemUpdateManyWithoutFolderInput at value.items.",
          "locations": [
            {
              "line": 7,
              "column": 2
            }
          ],
          "path": [
            "updateFolder"
          ]
        }
      ]
    }

Here’s the mutation:

    mutation UpdateFolder(
      $id: ID!,
      $state: String,
      $name: String,
      $items: [ItemWhereInput]
    ) {
     updateFolder(
      id: $id
      state: $state,
      name: $name,
      items: $items,
    	)
      {
        id
        name
      }
    }

And variables passed to the mutation:

    {
      "id": "cjelrwdrm000s0102c3fxhc84",
      
      "items": [
      {
        "id": "cjelswuq3000z0102tsiefn4k",
        "title": "meh"
      },
      {
        "id": "cjelsy06f001601022ezfalu2",
        "title": "amazon"
      }
      ]
    }

Relevant resolver:

      async updateFolder(parent, args, ctx, info) {
        const { id, ...data } = args
        const userId = getUserId(ctx)
        const folderExists = await ctx.db.exists.Folder({
          id,
          user: { id: userId },
        })
        if (!folderExists) {
          throw new Error(`Folder not found`)
        }

        return ctx.db.mutation.updateFolder(
          {
            where: { id },
            data,
          },
          info
        )
      },

Relevant Schema from src/generated/prisma.graphql:

    type Folder implements Node {
      id: ID!
      createdAt: DateTime!
      updatedAt: DateTime!
      name: String!
      state: String!
      user(where: UserWhereInput): User!
      column(where: ColumnWhereInput): Column!
      items(where: ItemWhereInput, orderBy: ItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Item!]
    }

    type Item implements Node {
      id: ID!
      createdAt: DateTime!
      updatedAt: DateTime!
      icon: String!
      href: String!
      desc: String
      title: String!
      keywords: String
      user(where: UserWhereInput): User!
      folder(where: FolderWhereInput): Folder!

    input ItemUpdateManyWithoutFolderInput {
      create: [ItemCreateWithoutFolderInput!]
      connect: [ItemWhereUniqueInput!]
      disconnect: [ItemWhereUniqueInput!]
      delete: [ItemWhereUniqueInput!]
      update: [ItemUpdateWithWhereUniqueWithoutFolderInput!]
      upsert: [ItemUpsertWithWhereUniqueWithoutFolderInput!]
    }```

#2

The updateFolder mutation you send to the Prisma API has this shape:

mutation {
  updateFolder(
    where: { id: "c..." }
    data: {
      items: [{ id: "c...", title: "meh" }, { id: "c...", title: "amazon" }]
    }
  )
}

data.items is supposed to be of type ItemUpdateManyWithoutFolderInput. The value you entered for data.items is not compatible with the expected shape of the ItemUpdateManyWithoutFolderInput type.

I recommend to first run the mutation in the Playground against the Prisma API, then you can use autocompletion to see what the expected shape is :slight_smile:


General note: You can typically debug those kind of errors more easily if you activated the debug: true option in your GraphQL Yoga server. Then all GraphQL operations + variables will be printed to stdout when they are executed, and you can handpick them and manually run them against the Playground against your Prisma API to see if you can reproduce the issue.


#3

Hi nilan,

Thank you so much for answering! I’m still struggling with this.

Here’s a few questions/observations:

  1. I’m running Prisma 1.5.3, do I need to update for this to work?

  2. When you say:

I presume you’re referring to the “database” > “dev” left panel section in the playground?

  1. The mutation shape you suggested produces an error in the “app” > “default” section. This is fine, but I ultimately need this to work from Apollo Client. Is there any guidance on converting between the Prisma (“database”?) API and the “app” API?

So that’s still the case with the mutation shape you provided above.

The key question then is how do I determine the expected shape of the ItemUpdateManyWithoutFolderInput type?

Searching though src/generated/prisma.graphql:

input ItemUpdateManyWithoutFolderInput {
...
  update: [ItemUpdateWithWhereUniqueWithoutFolderInput!]
...
input ItemUpdateWithWhereUniqueWithoutFolderInput {
  where: ItemWhereUniqueInput!
  data: ItemUpdateWithoutFolderDataInput!
}
input ItemUpdateWithoutFolderDataInput {
  icon: String
  href: String
  desc: String
  title: String
  keywords: String
  user: UserUpdateOneInput

Providing all appropriate values described in ItemUpdateWithoutFolderDataInput yields this mutation:

mutation{
 updateFolder(
  where: {id: "cjelrwdrm000s0102c3fxhc84"}
  data: {
    items: [
      {
        id: "cjelswuq3000z0102tsiefn4k",
        icon: "/static/prototype/icons/meh.png",
        href: "https://meh.com/",
        title: "meh",
        desc: "meh daily deals site",
        keywords: null
        user: {
          id: "cjefwvowl004z011733glutpy"
        }
      },
      {
        id: "cjelsy06f001601022ezfalu2",
        icon: "/static/prototype/icons/amazon.png",
        href: "https://amazon.com/",
        title: "amazon",
        desc: "Amazon shopping site",
        keywords: null
        user: {
          id: "cjefwvowl004z011733glutpy"
        }
      }
    ]
  }
	) {
   id
  }
}

Executing this mutation produces two errors:
"message": "Argument 'data' expected type 'FolderUpdateInput!' but got: {items: [{id: "c...
and:
Reason: 'items' Expected 'ItemUpdateManyWithoutFolderInput', found not an object. (line 4, column 9): data: {...

As before, if I remove items and update another, non-relational field it works as expected.


#4

OK, so I updated everything to latest
prisma 1.9.0
prisma-binding 2.0.2
graphql-yoga 1.14.7
graphql-cli 2.16.3

I updated and reconfigured docker-compose.yml and worked through related issues.

I still have the same issue, but now the errors/guidance presented in the playground are more helpful.

I have come to the conclusion that what I’m trying to do is not correct, so I’m redesigning my architecture.