Prisma报错Unknown argument aliases,关联字段插入失败如何解决?
Prisma插入关联数据报错:Unknown argument aliases的解决方法
问题描述
向包含aliases关联字段的Language模型插入数据时,触发报错:
Unknown argument aliases. Available options are listed in green.
预期数据能成功存入数据库,但实际出现上述错误,相关代码如下:
schema.prisma
model Language { id Int @id @default(autoincrement()) name String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt pastes Paste[] @relation("paste_language") aliases LanguageAlias[] @relation("language_alias") extensions LanguageExtension[] @relation("language_extension") @@map("language") }
seedLanguage.js
const { languages } = require("@codemirror/language-data"); async function createFakeLanguages(nbLanguages) { if (!nbLanguages || typeof nbLanguages !== "number" || nbLanguages < 0) { throw new Error('Le paramètre "nbLanguages" doit être un nombre positif.'); } const languageList = []; for (let i = 0; i < languages.length && i < nbLanguages; i++) { const languageName = languages[i]?.name || ""; const arrAliases = (languages[i]?.alias || []) .filter((alias) => typeof alias === "string") .map((alias) => ({ name: alias })); const arrExtensions = (languages[i]?.extensions || []) .filter((extension) => typeof extension === "string") .map((extension) => ({ name: extension })); languageList.push({ name: languageName, aliases: { create: arrAliases, }, extensions: { create: arrExtensions, }, }); } return languageList; } async function seedLanguage(prisma, nbLanguages) { try { const languageList = await createFakeLanguages( nbLanguages ); await prisma.language.createMany({ data: languageList, }); } catch (e) { e.functionName = "seedLanguage"; throw e; } } module.exports = seedLanguage;
seed.js(主脚本)
const { PrismaClient } = require("@prisma/client"); const prisma = new PrismaClient(); const seedLanguage = require("./seedLanguage"); async function runSeeds() { try { console.log("Starting seed process..."); if (!prisma.$connect) { throw new Error("Prisma client has not been properly initialized."); } console.log("Executing seedLanguage()..."); const nbLanguages = 10; await seedLanguage(prisma, nbLanguages); } catch (e) { console.error( "Error while executing seed function:", e.functionName ); console.error("Error details:", e); process.exit(1); } finally { await prisma.$disconnect(); } } runSeeds();
错误原因
你使用了createMany批量创建Language数据,但Prisma的createMany不支持嵌套创建关联数据(也就是代码里aliases.create、extensions.create这种嵌套操作)。createMany只能处理模型自身的字段,无法识别关联字段的嵌套创建语法,所以会把aliases当成普通字段,而你的Language模型里并没有这个普通字段,因此报错。
解决方法
有两种可行的修复方式,根据数据量和需求选择:
方式一:循环调用create替代createMany
把批量创建逻辑改成逐个调用create,每个Language单独创建时嵌套处理关联数据,修改seedLanguage.js中的seedLanguage函数即可:
async function seedLanguage(prisma, nbLanguages) { try { const languageList = await createFakeLanguages(nbLanguages); // 循环创建每个Language,同时处理关联 for (const languageData of languageList) { await prisma.language.create({ data: languageData, }); } } catch (e) { e.functionName = "seedLanguage"; throw e; } }
这种方式简单直接,适合数据量不大的场景,不需要修改其他逻辑。
方式二:分两步创建(先Language,再关联数据)
如果数据量较大,这种方式性能更优,分两步完成:
- 先批量创建所有Language,只包含自身字段
- 再批量创建对应的aliases和extensions,关联到对应的Language
修改后的seedLanguage.js示例:
const { languages } = require("@codemirror/language-data"); async function createFakeLanguages(nbLanguages) { if (!nbLanguages || typeof nbLanguages !== "number" || nbLanguages < 0) { throw new Error('Le paramètre "nbLanguages" doit être un nombre positif.'); } const languageDataList = []; const aliasesToCreate = []; const extensionsToCreate = []; for (let i = 0; i < languages.length && i < nbLanguages; i++) { const languageName = languages[i]?.name || ""; languageDataList.push({ name: languageName }); // 收集别名和扩展名,暂存关联的语言名称 const arrAliases = (languages[i]?.alias || []) .filter((alias) => typeof alias === "string") .map((alias) => ({ name: alias, languageName })); aliasesToCreate.push(...arrAliases); const arrExtensions = (languages[i]?.extensions || []) .filter((extension) => typeof extension === "string") .map((extension) => ({ name: extension, languageName })); extensionsToCreate.push(...arrExtensions); } return { languageDataList, aliasesToCreate, extensionsToCreate }; } async function seedLanguage(prisma, nbLanguages) { try { const { languageDataList, aliasesToCreate, extensionsToCreate } = await createFakeLanguages(nbLanguages); // 第一步:批量创建所有Language await prisma.language.createMany({ data: languageDataList, }); // 获取已创建的Language,建立名称到id的映射 const languages = await prisma.language.findMany({ where: { name: { in: languageDataList.map(l => l.name) } }, select: { id: true, name: true } }); const languageIdMap = new Map(languages.map(l => [l.name, l.id])); // 转换关联数据,绑定对应的languageId const finalAliases = aliasesToCreate.map(a => ({ name: a.name, languageId: languageIdMap.get(a.languageName) })); const finalExtensions = extensionsToCreate.map(e => ({ name: e.name, languageId: languageIdMap.get(e.languageName) })); // 第二步:批量创建关联数据 if (finalAliases.length > 0) { await prisma.languageAlias.createMany({ data: finalAliases }); } if (finalExtensions.length > 0) { await prisma.languageExtension.createMany({ data: finalExtensions }); } } catch (e) { e.functionName = "seedLanguage"; throw e; } } module.exports = seedLanguage;
补充说明
这种方式需要你的LanguageAlias和LanguageExtension模型包含languageId外键字段,如果schema里还没定义,需要补充:
model LanguageAlias { id Int @id @default(autoincrement()) name String languageId Int language Language @relation("language_alias", fields: [languageId], references: [id]) @@unique([name, languageId]) // 可选,避免同一语言下重复别名 } model LanguageExtension { id Int @id @default(autoincrement()) name String languageId Int language Language @relation("language_extension", fields: [languageId], references: [id]) @@unique([name, languageId]) // 可选,避免同一语言下重复扩展名 }
内容的提问来源于stack exchange,提问作者user21252219
相关产品推荐
相关产品推荐

