Search code examples
postgresqlnext.jsprisma

How can I create a nested item in the DB?


I am having several problems when I try to create a new user with a nested related table. My schema is like this:

model User {
    id                Int                 @id @default(autoincrement())
    username          String              @unique
    email             String              @unique
    avatar            String              @default("none")
    role              Role                @default(USER)
    password          String
    maxScore          Int                 @default(0)
    UserCategoryStats UserCategoryStats[]
}

model UserCategoryStats {
    id               Int      @id @default(autoincrement())
    user             User     @relation(fields: [userId], references: [id])
    userId           Int
    category         Category @relation(fields: [categoryId], references: [id])
    categoryId       Int
    correctAnswers   Int      @default(0)
    incorrectAnswers Int      @default(0)
    totalAnswers     Int      @default(0)
    timesChosen      Int      @default(0)
}

And I am just trying to create an user with one(or more) UserCategoryStats like the docs say Like this:

const newUser = await prisma.user.create({
    data: {
      username,
      email,
      password: hashedPassword,
      UserCategoryStats: {
        create: { //Here is the error
          correctAnswers: 0,
          incorrectAnswers: 0,
          totalAnswers: 0,
          timesChosen: 0,
        },
      },
    },
    include: {
      UserCategoryStats: true,
    },
  });

This is giving me this Typescript error :

Type '{ correctAnswers: number; incorrectAnswers: number; totalAnswers: number; timesChosen: number; }' is not assignable to type '(Without<UserCategoryStatsCreateWithoutUserInput, UserCategoryStatsUncheckedCreateWithoutUserInput> & UserCategoryStatsUncheckedCreateWithoutUserInput) | ... 5 more ... | undefined'. Type '{ correctAnswers: number; incorrectAnswers: number; totalAnswers: number; timesChosen: number; }' is not assignable to type 'undefined'

I have tried with multiple values but I simply dont know what is wrong. I am not able to create nested properties.

What am I doing wrong?


Solution

  • Considering the Prisma Query and Schema that you have shared there were no typescript errors, it can be that your PrismaClient is not in sync with the schema, you can execute npx prisma generate to verify if both are in sync.

    Here's a working example:

    main.ts

    import { PrismaClient } from '@prisma/client';
    
    const prisma = new PrismaClient({
      log: ['query'],
    });
    
    async function main() {
      const newUser = await prisma.user.create({
        data: {
          username: 'alice',
          email: '[email protected]',
          password: 'Prisma@111',
          UserCategoryStats: {
            create: {
              //Here is the error
              correctAnswers: 0,
              incorrectAnswers: 0,
              totalAnswers: 0,
              timesChosen: 0,
            },
          },
        },
        include: {
          UserCategoryStats: true,
        },
      });
    
      console.log(newUser);
    }
    
    main()
      .catch((e) => {
        throw e;
      })
      .finally(async () => {
        await prisma.$disconnect();
      });
    
    

    Response:

    > ts-node index.ts
    
    prisma:query BEGIN
    prisma:query INSERT INTO "public"."User" ("username","email","avatar","password","maxScore") VALUES ($1,$2,$3,$4,$5) RETURNING "public"."User"."id"
    prisma:query INSERT INTO "public"."UserCategoryStats" ("userId","correctAnswers","incorrectAnswers","totalAnswers","timesChosen") VALUES ($1,$2,$3,$4,$5) RETURNING "public"."UserCategoryStats"."id"
    prisma:query SELECT "public"."User"."id", "public"."User"."username", "public"."User"."email", "public"."User"."avatar", "public"."User"."password", "public"."User"."maxScore" FROM "public"."User" WHERE "public"."User"."id" = $1 LIMIT $2 OFFSET $3
    prisma:query SELECT "public"."UserCategoryStats"."id", "public"."UserCategoryStats"."userId", "public"."UserCategoryStats"."correctAnswers", "public"."UserCategoryStats"."incorrectAnswers", "public"."UserCategoryStats"."totalAnswers", "public"."UserCategoryStats"."timesChosen" FROM "public"."UserCategoryStats" WHERE "public"."UserCategoryStats"."userId" IN ($1) OFFSET $2
    prisma:query COMMIT
    {
      id: 1,
      username: 'alice',
      email: '[email protected]',
      avatar: 'none',
      password: 'Prisma@111',
      maxScore: 0,
      UserCategoryStats: [
        {
          id: 1,
          userId: 1,
          correctAnswers: 0,
          incorrectAnswers: 0,
          totalAnswers: 0,
          timesChosen: 0
        }
      ]
    }
    
    

    Inserted Data:

    enter image description here