Search code examples
postgresqlgraphqlapolloprisma

How can I use createMany with foreign keys in prisma?


I am a beginner in using Prisma and am stuck at trying to figure out how to initially load data into postgres tables. I have tried seeding my db as per this example in prisma https://github.com/prisma/prisma-examples/tree/latest/javascript/graphql-auth but it seems the main() is not getting triggered by the command "npx prisma db seed --preview-feature". So I tried to insert into my db through a temporary function but I am getting an invalid invocation error on starting dev server:

Foreign key constraint failed on the field: Animals_categoryName_fkey (index)

But I am not getting this error when I don't use foreign keys. Below is my schema.prisma, types and the data that I need to add.

Schema.prisma

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model Animals{
  id Int @id @default(autoincrement())
  image String
  price String
  description String[]
  stock Int
  onSale Boolean
  title String
  category Category @relation(fields: [categoryName], references: [categoryName])
  slug String @unique
  categoryName String
}

model Category{
  id Int @id @default(autoincrement())
  image String
  categoryName String @unique
  animals Animals[]
}

model MainCards{
  cardId Int @id @default(autoincrement())
  image String
  title String
}

typedefs--

const typeDefs = gql`
      type MainCard {
          title: String!
          image: String!
      }
    
      type Animals{
        id: ID!
        image: String!
        price: String!
        description: [String!]!
        stock: Int!
        onSale: Boolean
        slug: String
        categoryName: String
        title: String
      }
    
      type Category{
        id: ID!
        image: String!
        categoryName: String!
      }
    
      type Query {
        mainCards: [MainCard]
        animals: [Animals]
        animal(slug: String!): Animals
        categories: [Category]
        category(categoryName: String!): [Animals]
      }
    `;

Part of data to add:

const AnimalsData = async () => {
    await prisma.animals.createMany({
        data: [
            {
                image: "lion",
                title: "7-year Male Lion with Large Well Kept Main with a Beautiful Yellow/Brownish Color",
                price: "23,322",
                description: [
                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                    "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
                    "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
                    "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
                ],
                stock: 14,
                onSale: false,
                slug: "lion",
                categoryName: "cats"
            },            
            {
                image: "gorilla",
                title: "Black Haired Gorilla with Broad Chest and Shoulder. Would be an Excellent Spot at the Gym",
                price: "47,775",
                description: [
                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                    "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
                    "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
                    "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
                ],
                stock: 14,
                onSale: false,
                slug: "gorilla",
                categoryName: "mammals"
            }            
        ]
    })
}

AnimalsData()
.catch(e => {throw e})
.finally(async () => {await prisma.$disconnect()})

If it helps in any way, I am using prisma 2.24, apollo and graphql with a postgres database. Any help or suggestion is greatly appreciated.


Solution

  • Prisma will not let you create a Animal record with a certain foreign key provided in Animals.categoryName if there is no matching record with the same categoryName in the Category table. This is called a Foreign key constraint.

    To satisfy the Foreign key constraint you need to make sure a record already exists in the Category table with the same categoryName as the record you're trying to create in the Animals table. For the example you mentioned, this would mean creating two records in the Category table having Category.categoryName of "mammals" and "cats".

    Before running the animals.createMany query, you can do something like this,

    await prisma.category.createMany({
            data: [
                {
                    categoryName: "mammals",
                    image: "__PLACEHOLDER_VALUE__"  // change appropriately
                },
                {
                    categoryName: "cats",
                    image: "__PLACEHOLDER_VALUE__"  // change appropriately
                }
            ]
        })
    
    //  ...run await prisma.animals.createMany 
    

    It's not possible to create both Animal and Category wih a single createMany query because you cannot access relations in a CreateMany query. If this is something you want to do, consider using create instead of createMany. You can find more information about this in the nested writes section of the Prisma docs.