2

I'm playing around with seeding in Prisma and I'm struggling to find examples that aren't super basic. In the example below, I want to create a User (author) who has authored multiple Services (1:n) and each Service has can come from one Provider.

  • User - 1:n - Services
  • Services m:1 - Provider

In the example below, the creation process results in 3 instances of "AWS" on the Provider table. Which, makes sense given the syntax used. I'd like to just have one Record of AWS, GCP, and AZURE (my provider enums) respectively.

Also, if anyone has a more eloquent example of how to generate this to be more scalable of a seed please let me know.

seed.ts

const main = async () => {
  await prisma.user.create({
    data: {
      email: "moderator@gmail.com",
      username: "timothy",
      role: "MODERATOR",
      authored: {
        create: [
          {
            name: "Simple Storage Service",
            acronym: "S3",
            provider: {
              create: {
                name: "AWS", // how can these all reference the same Provider table row?
              },
            },
          },
          {
            name: "DynamoDB",
            acronym: "DynamoDB",
            provider: {
              create: {
                name: "AWS",
              },
            },
          },
          {
            name: "API Gateway",
            acronym: "API Gateway",
            provider: {
              create: {
                name: "AWS",
              },
            },
          },
          {
            name: "BigQuery",
            acronym: "BigQuery",
            provider: {
              create: {
                name: "GCP",
              },
            },
          },
        ],
      },
    },
  });
};

schema.prisma

enum Providers {
  AWS
  GCP
  AZURE
}

enum Role {
  USER
  MODERATOR
  ADMIN
}

model User {
  id        Int       @id @default(autoincrement())
  email     String    @unique @db.VarChar(255)
  username  String    @unique @db.VarChar(255)
  role      Role      @default(USER)
  createdAt DateTime  @default(now())
  authored  Service[]
}

model Service {
  id         Int      @id @default(autoincrement())
  name       String   @unique @db.VarChar(255)
  acronym    String   @unique @db.VarChar(255)
  authorId   Int
  providerId Int
  author     User     @relation(fields: [authorId], references: [id])
  provider   Provider @relation(fields: [providerId], references: [id])
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
}

model Provider {
  id        Int       @id @default(autoincrement())
  name      Providers
  Services  Service[]
  createdAt DateTime  @default(now())
}

Current result in the Provider's table. There should not be duplicates (triplicates) of "AWS".

enter image description here

kevin
  • 2,707
  • 4
  • 26
  • 58

2 Answers2

4

Just precreate provider and then connect it to the service:

const main = async () => {
  const awsProvider = await prisma.providers.create({
    data: { name: 'AWS' }
  })

  await prisma.user.create({
    data: {
      email: "moderator@gmail.com",
      username: "timothy",
      role: "MODERATOR",
      authored: {
        create: [
          {
            name: "Simple Storage Service",
            acronym: "S3",
            provider: {
              connect: awsProvider
            },
          },

// ...

Danila
  • 15,606
  • 2
  • 35
  • 67
  • It's almost working, currently troubleshooting the current error when I try to use your example and seed: Unknown arg `createdAt` in data.authored.create.2.provider.connect.createdAt for type ProviderWhereUniqueInput. Available args: type ProviderWhereUniqueInput {id?: Int}. I tried using `awsProvider.id` but it didn't like that. hmm. – kevin Feb 17 '22 at 18:03
  • when I use: `awsProvider.id` the following error returns: Type 'number' is not assignable to type 'ProviderWhereUniqueInput | undefined'. – kevin Feb 17 '22 at 18:08
  • I've resolved this issue and created a new answer below. Thank you for pointing me in the right direction! – kevin Feb 17 '22 at 18:15
4

I've resolved the issue, the example below shows how to connect or associate the tables in the seed.

here are the relevant Prisma docs.

const main = async () => {
  const awsProvider = await prisma.provider.create({
    data: { name: "AWS" },
  });
  const gcpProvider = await prisma.provider.create({
    data: { name: "GCP" },
  });

  await prisma.user.create({
    data: {
      email: "moderator@gmail.com",
      username: "timothy",
      role: "MODERATOR",
      authored: {
        create: [
          {
            name: "Simple Storage Service",
            acronym: "S3",
            provider: {
              connect: { id: awsProvider.id },
            },
          },
          {
            name: "DynamoDB",
            acronym: "DynamoDB",
            provider: {
              connect: { id: awsProvider.id },
            },
          },
          {
            name: "API Gateway",
            acronym: "API Gateway",
            provider: {
              connect: { id: awsProvider.id },
            },
          },
          {
            name: "BigQuery",
            acronym: "BigQuery",
            provider: {
              connect: { id: gcpProvider.id },
            },
          },
        ],
      },
    },
  });
};
kevin
  • 2,707
  • 4
  • 26
  • 58