Prisma多对多关联场景下如何用createMany批量创建数据?
解决方案
为什么你的代码报错
createMany 是 Prisma 专为单表批量插入设计的API,它的输入类型 PostCreateManyInput 仅包含Post表的直接字段(id、text),不支持嵌套的关联操作(比如phones.connectOrCreate),所以会提示未知参数phones。
实现批量创建的正确方式
因为涉及多对多关联,需要拆分三步操作,并用事务保证原子性:
- 批量创建/获取所有关联的Phone记录
- 批量创建Post记录
- 批量插入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
相关产品推荐
相关产品推荐

