I have a Disambiguating relations between two mode...
# orm-help
s
I have a Disambiguating relations between two models like this
Copy code
model Product {
  id          Int     @id @default(autoincrement())
  name        String?
  fees        Fee[]   @relation("fees")
  default_fee Fee?    @relation("default_fee")
}

model Fee {
  id             Int      @id @default(autoincrement())
  total          Float    @default(0)
  product_id     Int
  product        Product  @relation(name: "fees", fields: [product_id], references: [id], onDelete: Cascade)
  defaultable    Product? @relation(name: "default_fee", fields: [defaultable_id], references: [id])
  defaultable_id Int?     @unique
}
While fetching its works like expected. However while creating product with nested relations like this:
Copy code
const product = await this.prisma.product.create({
      data: {
       ...data,
        default_fee: {
          create: {
            // asks for product id
            total: 500,
          },
        },
      },
    });
It asks me for product id. But it doesn't make sense to pass product_id as I wouldn't have the product id at that point. I know I can make it work by breaking the query down, but nested create doesnot seem to work for disambiguating relations. I'm curious wether it's issue on prisma or I'm missing something here Repo Link: https://github.com/sagarPakhrin/prisma-disambiguating-relations/blob/master/src/app.service.ts
👀 1
1
n
Hey Sagar 👋 I think this is a current limitation of the Prisma Client API when working with required relations (that we might want to look into lifting though)! However, I also was wondering if maybe for your use case it was feasible to create the records “the other way around”, i.e. starting at the fee and then creating the associated product:
Copy code
const fee = await prisma.fee.create({
  data: {
    total: 100,
    product: {
      create: {
        name: "My Product"
      }
    }
  }
})
Or does this problem also persist when doing it this way?
s
Hi @nikolasburk Creating fee this way will only create fee, but not default fee.
👍 1
n
Ah yes, you’re right! Would you mind opening an issue for this? This is an interesting edge case for the Prisma Client API, as a workaround I think you’ll have to break it down into multiple Prisma Client queries drop down to raw SQL with
$queryRaw
unfortunately 😕
s
Initially I thought breaking in into multiple query would work by creating product and then creating fees later would solve the issue
Copy code
const product = await this.prisma.product.create({
      data: {
        name: 'product1',
      },
    });

    const fee = await this.prisma.fee.create({
      data: {
        total: 100,
        defaultable_id: product.id,
        product: {
          connect: {
            id: product.id,
          },
        },
      },
    });
But still it gives me any error saying
Copy code
Types of property 'defaultable_id' are incompatible.
        Type 'number' is not assignable to type 'never'
I'll be opening an issue
🙏 2
b
Didn't se before , but for me i make same than your second aproach and this working
👌 1
this is my query in my case if that can help you
Copy code
await prisma.cibest_role.create({
    data: {
      name: "super admin",
      description: "Role qui à tous les droits",
      feature: {
        create: [
          {
            service_name: "role",
            create: true,
            read: true,
            update: true,
            delete: true,
          },
          {
            service_name: "authentication",
            create: true,
            read: true,
            update: true,
            delete: true,
          },
        ],
      },
    },
  });
  await prisma.cibest_user.create({
    data: {
      email: "<mailto:super-admin@cibest.com|super-admin@cibest.com>",
      first_name: "John",
      last_name: "Doe",
      password: hash,
      avatar: "<https://robohash.org/john> doe",
      cibest_users_roles: {
        create: { cibest_role: { connect: { name: "super admin" } } },
      },
    },
  });
}
🙏 1
and the model
Copy code
model cibest_user {
  id                 String               @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  date_created       DateTime             @default(now()) @db.Timestamp(6)
  first_name         String               @db.VarChar(64)
  last_name          String               @db.VarChar(64)
  email              String               @unique @db.VarChar(64)
  password           String               @db.VarChar
  ldap_account       Boolean?
  ldap_id            String?              @db.VarChar
  addressId          String?              @db.Uuid
  avatar             String?
  languageId         String?              @db.Uuid
  address            address?             @relation(fields: [addressId], references: [id])
  language           language?            @relation(fields: [languageId], references: [id])
  cibest_user_agency cibest_user_agency[]
  cibest_users_roles cibest_users_roles[]
  token              token[]
}
Copy code
model cibest_users_roles {
  cibest_user_id String      @db.Uuid
  cibest_role_id String      @db.Uuid
  cibest_role    cibest_role @relation(fields: [cibest_role_id], references: [id])
  cibest_user    cibest_user @relation(fields: [cibest_user_id], references: [id])

  @@id([cibest_role_id, cibest_user_id])
}
Copy code
model cibest_role {
  id                 String               @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  date_created       DateTime             @default(now()) @db.Timestamp(6)
  name               String               @unique @db.VarChar(32)
  description        String
  iconId             String?              @db.Uuid
  icon               icon?                @relation(fields: [iconId], references: [id])
  cibest_users_roles cibest_users_roles[]
  feature            feature[]
}
MTM relation