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

Prisma多对多关联场景下如何用createMany批量创建数据?

解决方案

为什么你的代码报错

createMany 是 Prisma 专为单表批量插入设计的API,它的输入类型 PostCreateManyInput 仅包含Post表的直接字段(id、text),不支持嵌套的关联操作(比如phones.connectOrCreate),所以会提示未知参数phones。

实现批量创建的正确方式

因为涉及多对多关联,需要拆分三步操作,并用事务保证原子性:

  1. 批量创建/获取所有关联的Phone记录
  2. 批量创建Post记录
  3. 批量插入Post与Phone的关联数据(Prisma自动生成中间表)

完整代码示例

await prisma.$transaction(async (tx) => {
    // 1. 提取所有唯一的手机号,避免重复创建
    const allUniquePhones = [...new Set(posts.flatMap(item => item.phones))];

    // 批量创建Phone,已存在的跳过(依赖phone字段的@unique约束)
    await tx.phone.createMany({
        data: allUniquePhones.map(phone => ({ phone })),
        skipDuplicates: true
    });

    // 建立手机号到ID的映射,方便后续关联
    const phoneRecords = await tx.phone.findMany({
        where: { phone: { in: allUniquePhones } },
        select: { id: true, phone: true }
    });
    const phoneIdMap = new Map(phoneRecords.map(p => [p.phone, p.id]));

    // 2. 批量创建Post记录
    const createdPosts = await tx.post.createMany({
        data: posts.map(item => ({ text: item.text })),
        // Prisma 4.16+ 支持select,直接返回创建后的ID和text
        select: { id: true, text: true }
    });
    const postIdMap = new Map(createdPosts.map(p => [p.text, p.id]));

    // 3. 生成多对多关联数据,批量插入中间表
    const postPhoneRelations = posts.flatMap(item => {
        const postId = postIdMap.get(item.text);
        return item.phones.map(phone => ({
            postId,
            phoneId: phoneIdMap.get(phone)
        }));
    });

    await tx.postPhone.createMany({
        data: postPhoneRelations
    });
});

注意事项

  • 中间表名由Prisma自动生成,规则是两个模型名首字母大写拼接(比如Post和Phone对应PostPhone),你可以通过prisma studio查看实际表名。
  • 如果Post的text字段不唯一,建议改用其他唯一标识关联Post记录,或者在创建Post时额外携带自定义唯一字段。
  • skipDuplicates: true 依赖Phone表中phone字段的@unique约束,确保不会重复插入相同手机号。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 10:37:29