You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Prisma中实现多对多关系的数据批量插入?

问题描述

我曾尝试使用connect和connectOrCreate方法,但未能成功实现需求。我的需求是:每次插入采购记录时,可能会关联多个产品,希望传入包含这些产品的数组/JSON数据,一次性完成采购、产品及中间关联表的插入操作。

模型定义

model Category {
  id      Int       @id @default(autoincrement())
  name    String    @unique @db.VarChar(50)
  product Product[]

  @@map("categories")
}

model Product {
  id         Int         @id @default(autoincrement())
  name       String      @unique @db.VarChar(35)
  barcode    String      @unique @db.VarChar(35)
  sell       Decimal     @db.Decimal(12, 2)
  shop       Decimal     @db.Decimal(12, 2)
  quantity   Int
  expiresIn  String
  createdAt  DateTime    @default(now())
  updatedAt  DateTime    @updatedAt
  categoryId Int
  category   Category    @relation(fields: [categoryId], references: [id], onDelete: Cascade, onUpdate: Cascade)
  sales      SaleOrder[]
  purchases  PurchaseProduct[]
  
  @@map("products")
}

model PurchaseProduct{
  name       String    @db.VarChar(50)
  sell       Decimal   @db.Decimal(12, 2)
  shop       Decimal   @db.Decimal(12, 2)
  quantity   Int
  expiresIn  String
  purchaseId Int
  purchase   Purchase  @relation(fields: [purchaseId], references: [id], onDelete: Cascade, onUpdate: Cascade)
  productId  Int
  product    Product   @relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: Cascade)

  @@id([purchaseId, productId])

  @@map("purchaseProducts")
}

model Purchase{
  id         Int     @id @default(autoincrement())
  supplierId Int
  supplier   Supplier @relation(fields: [supplierId], references: [id], onDelete: Cascade, onUpdate: Cascade)
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt

  purchases  PurchaseProduct[]
  @@map("purchases")
}

model Supplier {
  id          Int       @id @default(autoincrement())
  name        String    @unique @db.VarChar(35)
  email       String?   @unique @db.VarChar(35)
  contact     String?   @unique @db.VarChar(10)
  products    Purchase[]

  @@map("suppliers")
}

尝试过的代码

export async function create(formData: Purchase){
  const purchase = await db.purchase.create({
    data:   {
      name: formData.name,
      sell: formData.sell,
      shop: formData.shop,
      quantity: formData.quantity,
      supplier: {
                  connectOrCreate:{
                    where:{name: formData.supplierName},
                    create:{name: formData.supplierName, contact: formData.phone, email: formData.email}
                }
              },
      product:{
                connectOrCreate:{where:{name:formData.name}, 
                create:{
                      name: FormData.name,
                      barcode: formData.barcode,
                      sell:formData.sell,
                      shop: formData.shop,
                      quantity: formData.quantity,
                      expiresIn: formData.expiresIn,
                      categoryId: formData.categoryId
                    }}
                }}
              })
              
  return purchase;
}
解决方案

核心问题是未正确利用Prisma多对多关联的嵌套写入语法,且原代码仅支持单个产品处理,未适配数组传入场景。以下是修正后的实现:

首先调整入参类型,确保包含产品数组,再通过purchases字段(对应中间表PurchaseProduct)批量创建关联关系,同时对每个产品执行connectOrCreate:

// 定义符合需求的入参类型(可根据实际业务调整)
interface PurchaseCreateInput {
  supplierName: string;
  phone?: string;
  email?: string;
  products: Array<{
    name: string;
    barcode: string;
    sell: number;
    shop: number;
    quantity: number;
    expiresIn: string;
    categoryId: number;
    // 中间表自身需要的字段
    purchaseName: string;
    purchaseSell: number;
    purchaseShop: number;
    purchaseQuantity: number;
    purchaseExpiresIn: string;
  }>;
}

export async function create(formData: PurchaseCreateInput) {
  const purchase = await db.purchase.create({
    data: {
      // 供应商关联逻辑保留
      supplier: {
        connectOrCreate: {
          where: { name: formData.supplierName },
          create: {
            name: formData.supplierName,
            contact: formData.phone,
            email: formData.email
          }
        }
      },
      // 批量处理产品与中间表的关联
      purchases: {
        create: formData.products.map(product => ({
          // 填充中间表自身字段
          name: product.purchaseName,
          sell: product.purchaseSell,
          shop: product.purchaseShop,
          quantity: product.purchaseQuantity,
          expiresIn: product.purchaseExpiresIn,
          // 处理产品的连接或创建
          product: {
            connectOrCreate: {
              where: { name: product.name }, // 用唯一字段匹配已有产品
              create: {
                name: product.name,
                barcode: product.barcode,
                sell: product.sell,
                shop: product.shop,
                quantity: product.quantity,
                expiresIn: product.expiresIn,
                categoryId: product.categoryId
              }
            }
          }
        }))
      }
    },
    // 可选:返回关联数据便于验证结果
    include: {
      supplier: true,
      purchases: {
        include: { product: true }
      }
    }
  });

  return purchase;
}

关键说明

  • 中间表操作逻辑:Purchase与Product通过PurchaseProduct中间表关联,需操作Purchase的purchases字段创建中间表记录,而非直接操作product字段。
  • 数组批量处理:使用map将传入的产品数组转换为Prisma要求的create数组,实现一次性批量插入。
  • 字段匹配:确保中间表的自有字段正确赋值,同时保留产品的connectOrCreate逻辑,保证产品不存在时自动创建。

内容的提问来源于stack exchange,提问作者Armando Nhica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 07:11:11