Having trouble with data relationships

I’m having trouble with this data one-to-many data relationship. I can’t seem to use the create mutation without an error. I created the following schema with a one-to-many relationship

model Roaster {
  id           String   @id @default(uuid())
  name         String
  addressLine1 String?
  addressLine2 String?
  city         String?
  state        String?
  postalCode   String?
  coffees      Coffee[]
}

model Coffee {
  id        String   @id @default(uuid())
  name      String
  roaster   Roaster? @relation(fields: [roasterId], references: [id])
  roasterId String?

  @@unique([id, roasterId])
}

The generated graphql shows that the create coffee input is

type CreateCoffeeInput {
name: String!
roasterId: String
}

which makes sense…however, when I try to make a mutation, either through the generated scaffold page, or directly from the graphql playground, I get the following error.

 "Unknown arg `roasterId` in data.roasterId for type CoffeeCreateInput. Did you mean `roaster`? Available args:",
            "type CoffeeCreateInput {",
            "  id?: String",
            "  name: String",
            "  roaster?: RoasterCreateOneWithoutCoffeesInput",
            "}",

I’m not sure why on the outside, the generated schema wants a roasterId, but underneath, somewhere, it doesn’t recognize it.

Hi @roborich Thanks for checking in about this! It’s likely you’re running into a current limitation with Redwood Generators support for Prisma relations. Could you take a look at this workaround and see if it does the trick?

Your probably already aware how to do this manually without the generator, but in case anyone else is interested, this is a basic example of a post with many categories. If this solution could be written differently (i.e. better!), please let us know @thedavid.

I have just included the relevant parts for the relationship.

primsa/schema.primsa

model Post {
  id         Int        @id @default(autoincrement())
  title      String
  body       String
  categories Category[] @relation(references: [id])
}

model Category {
  id    Int    @id @default(autoincrement())
  name  String
  posts Post[] @relation(references: [id])
}

graphql/posts.sdl

  input CreatePostInput {
    title: String!
    body: String!
    categories: [CategoriesInput]
  }

  input CategoriesInput {
    id: Int!
  }

/services/posts.js

export const createPost = ({ input }) => {
  return db.post.create({
    data: {
      title: input.title,
      body: input.body,
      categories: {
        connect: input.categories,
      },
    },
  })
}

/components/PostForm

const PostForm = (props) => {
  const onSubmit = (data) => {
    data.categories.forEach(function (category, index) {
      this.categories[index] = {
        id: parseInt(category),
      }
    }, data)
    props.onSave(data, props?.post?.id)
  }
2 Likes

Hi @roborich

Not sure if this will help, but maybe will point you in a direction … I too had some

experience recently when I was trying to use Prisma CRUD (well Create/Upsert ) with relations and realized that the Prisma-way takes some getting used to coming from say ActiveRecord or straight SQL.

I was seeing <model>CreateManyWithout<relations>Input and I had no idea where that was coming from since it wasn’t in the sdl.

I had to read the Prisma CRUD and see their examples:

export type PostCreateManyWithoutAuthorInput = {
  create?: Enumerable<PostCreateWithoutAuthorInput> | null
  connect?: Enumerable<PostWhereUniqueInput> | null
}
export type PostCreateWithoutAuthorInput = {
  title: string
  published?: boolean | null
  comments?: object | null
}

to learn that a connect: needs to be set.

I also had a compound unique index set on my relation.

return await db.deploy.upsert({
    where: { id: data.id },
    update: {
      ...data,
    },
    create: {
      ...data,
      user: { connect: { id: user.id } },
      site: { connect: { id: site.id } },
    },
  })

I found I had to use the connect as almost some sort of join condition.

White it doesn’t appear that the CreateOneWithout flavor of this needs a connect it may be worth a try to do:

roaster: { connect: { id: roasterId } } in your mutation.

1 Like