这是我第一次使用后端,在本例中,我在 Next.js 中使用带有 SQLite 数据库的 Prisma ORM。作为我打算如何工作的概述:
用户可以访问Boards,其中可以有许多用户,并且Users可以有许多Boards。
Boards 包含 Items(在本例中,电影是通过 movieDB api 拉入的。)
Items有一个Ranks列表(从S到D)。 排名由用户组织,以跟踪谁对哪个项目进行排名,以便我可以显示每个人对某个项目的排名,并对排名进行平均以显示所有项目的单独板平均排名项目。
我并不完全理解 Prisma 文档中隐式与显式关系的关系,可以在这里使用一些指导。
这是我的架构:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
email String @unique
name String?
boards Board[]
ownedBoards Board[] @relation("BoardOwner")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
Rank Rank[]
}
model Board {
id String @id @default(uuid())
boardName String
owner User @relation("BoardOwner", fields: [ownerId], references: [id])
ownerId String
users User[]
userId String
items Items[]
}
model Items {
id Int @id @unique
name String
description String
poster String
backdrop String?
rank Rank[]
release_date String?
Board Board? @relation(fields: [boardId], references: [id], onDelete: Cascade)
boardId String?
}
model Rank {
User User @relation(fields: [userId], references: [id])
userId String
rank String
Items Items? @relation(fields: [itemsId], references: [id], onDelete: Cascade)
itemsId Int @id
}
这里是我在尝试为虚拟用户添加排名时在 Prisma Studio 中遇到的错误:
Type: undefined
Message:
Invalid `f=e.match(mgt)?.[1]??"",g=e.match(hgt)?.[1]??null,v=e.match(ggt)?.[1]??null,{getPrismaClient:E,PrismaClientKnownRequestError:x,PrismaClientRustPanicError:S,PrismaClientInitializationError:C,PrismaClientValidationError:A}=require(`${c.prismaClient}/runtime/${u}`),O=e,I=(0,Rk.createHash)("sha256").update()` invocation in
C:\Users\John\Developement\movie.night\movie.night\node_modules\prisma\build\index.js:1825:10334
1822 }
1823 }
1824 }
→ 1825 `}});return Oe.resourceList(a.workspaces)}};var G8e=require("@prisma/engines");var w2e=require("buffer");function _2e(e,r,n,i){Object.defineProperty(e,r,{get:n,set:i,enumerable:!0,configurable:!0})}var E2e={};_2e(E2e,"serializeRPCMessage",()=>KR);_2e(E2e,"deserializeRPCMessage",()=>YR);var WR="PrismaBigInt::",zR="PrismaBytes::";function KR(e){return JSON.stringify(e,(r,n)=>typeof n=="bigint"?WR+n:n?.type==="Buffer"&&Array.isArray(n?.data)?zR+w2e.Buffer.from(n.data).toString("base64"):n)}function YR(e){return JSON.parse(e,(r,n)=>typeof n=="string"&&n.startsWith(WR)?BigInt(n.substr(WR.length)):typeof n=="string"&&n.startsWith(zR)?n.substr(zR.length):n)}var N8e=$(O2e()),d9=$(w8e()),F8e=$(require("http")),$8e=$(S8e()),L8e=require("zlib");var Ts=require("path");var Rk=require("crypto"),O8e=$(Ck());function Ak(e,r,n,i){Object.defineProperty(e,r,{get:n,set:i,enumerable:!0,configurable:!0})}var R8e=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{},Tk={},l9={},Yu=R8e.parcelRequire1308;Yu==null&&(Yu=function(e){if(e in Tk)return Tk[e].exports;if(e in l9){var r=l9[e];delete l9[e];var n={id:e,exports:{}};return Tk[e]=n,r.call(n.exports,n,n.exports),n.exports}var i=new Error("Cannot find module '"+e+"'");throw i.code="MODULE_NOT_FOUND",i},Yu.register=function(r,n){l9[r]=n},R8e.parcelRequire1308=Yu);Yu.register("9lTzd",function(module,exports){Ak(module.exports,"guessEnginePaths",()=>guessEnginePaths),Ak(module.exports,"guessPrismaClientPath",()=>guessPrismaClientPath);var $5COlq=Yu("5COlq");async function guessEnginePaths({forceBinary,forceLibrary,resolveOverrides}){let queryEngineName,queryEngineType;if(forceLibrary?(queryEngineName=await $5COlq.prismaEngineName("query-engine","library"),queryEngineType="library"):forceBinary?(queryEngineName=await $5COlq.prismaEngineName("query-engine","binary"),queryEngineType="binary"):(queryEngineName=void 0,queryEngineType=void 0),!queryEngineName||!queryEngineType)return{queryEngine:void 0};let queryEnginePath;if(resolveOverrides[".prisma/client"])queryEnginePath=(0,Ts.resolve)(resolveOverrides[".prisma/client"],`../${queryEngineName}`);else if(resolveOverrides["@prisma/engines"])queryEnginePath=(0,Ts.resolve)(resolveOverrides["@prisma/engines"],`../../${queryEngineName}`);else{let atPrismaEnginesPath;try{atPrismaEnginesPath=eval("require.resolve('@prisma/engines')")}catch(e){throw new Error("Unable to resolve Prisma engine paths. This is a bug.")}queryEnginePath=(0,Ts.resolve)(atPrismaEnginesPath`../../${queryEngineName}`)}return{queryEngine:{type:queryEngineType,path:queryEnginePath}}}function guessPrismaClientPath({resolveOverrides}){let prismaClientPath=resolveOverrides["@prisma/client"]||eval("require.resolve('@prisma/client')");return(0,Ts.resolve)(prismaClientPath,"../")}});Yu.register("5COlq",function(e,r){Ak(e.exports,"prismaEngineName",()=>n);async function n(i,a){let o=await Er(),u=o==="windows"?".exe":"";if(a==="library")return ka(o,"fs");if(a==="binary")return`${i}-${o}${u}`;throw new Error(`Unknown engine type: ${a}`)}});function fgt(e){return{models:Pk(e.models),enums:Pk(e.enums),types:Pk(e.types)}}function Pk(e){let r={};for(let{name:n,...i}of e)r[n]=i;return r}var M2=(0,O8e.debug)("prisma:studio-pcw"),mgt=/^\s*datasource\s+([^\s]+)\s*{/m,hgt=/url *= *env\("(.*)"\)/,ggt=/url *= *"(.*)"/;async function vgt({schema:e,schemaPath:r,dmmf:n,datasourceProvider:i,previewFeatures:a,datasources:o,engineType:u,paths:c,directUrl:p,versions:l}){let f=e.match(mgt)?.[1]??"",g=e.match(hgt)?.[1]??null,v=e.match(ggt)?.[1]??null,{getPrismaClient:E,PrismaClientKnownRequestError:x,PrismaClientRustPanicError:S,PrismaClientInitializationError:C,PrismaClientValidationError:A}=require(`${c.prismaClient}/runtime/${u}`),O=e,I=(0,Rk.createHash)("sha256").update(
Unique constraint failed on the fields: (`itemsId`)
Code: P2002
代码 P2002 对应于“{constraint} 上的唯一约束失败”,不确定这意味着什么。
编辑以包含 prisma 功能,但是此错误发生在 Prisma Studio(Prisma 的基于 UI 的工具)中。这是第一次使用该工具,所以这些是我在尝试虚拟用户之前用来构建所有内容的工具:
"use server"
import prisma from "@/db"
export async function getBoards() {
return await prisma.board.findMany({
include: {
items: {
include: {
rank: true,
},
},
users: true,
owner: true,
},
})
}
export async function getSpecificBoard(boardId) {
return await prisma.board.findUnique({
where: { id: boardId },
include: {
items: {
include: {
rank: true,
},
},
users: true,
owner: true,
},
})
}
export async function getItems() {
return await prisma.items.findMany({
include: {
rank: true,
},
})
}
export async function getUsers() {
return await prisma.user.findMany({
include: {
boards: true,
ownedBoards: true,
},
})
}
export async function getUser(userId) {
return await prisma.user.findFirst({
where: { id: userId },
include: {
boards: true,
ownedBoards: true,
Rank: true,
},
})
}
export async function addItem(board, user, item) {
const boardId = board.id
await prisma.board.update({
where: { id: boardId },
data: {
items: {
create: {
id: item.id,
name: item.title,
description: item.overview,
poster: item.poster_path,
backdrop: item.backdrop_path,
release_date: item.release_date,
rank: {
create: {
rank: "",
User: {
connect: {
id: user.id,
},
},
},
},
},
},
},
include: {
items: true,
users: true,
},
})
}
export async function deleteItem(board, item) {
await prisma.board.update({
where: { id: board.id },
data: {
items: {
deleteMany: {
id: item.id,
},
disconnect: {
id: item.id,
},
},
},
include: {
items: {
include: {
Board: true,
},
},
},
})
}
export async function updateRank(item, user, score) {
// console.log("update start")
await prisma.board.update({
where: { id: item.boardId },
data: {
items: {
update: {
where: { id: item.id },
data: {
rank: {
upsert: {
create: {
rank: score,
User: {
connect: {
email: "[email protected]",
},
},
},
update: {
rank: score,
User: {
connect: {
email: "[email protected]",
},
},
},
where: { userId: user.id, itemsId: item.id },
},
},
},
},
},
},
include: {
items: true,
users: true,
},
})
}
export async function updateBoardName(board, newName) {
await prisma.board.update({
where: { id: board.id },
data: { boardName: newName },
})
}
花了一段时间才理解您想要实现的目标,但现在我相当有信心可以回答您的问题。让我尝试写下我是如何理解这个场景的:
您正在使用 Prisma Studio 手动将新的“排名”记录添加到包含一些种子/虚拟数据的数据库中。单击“保存”时,插入失败,代码为 P2002,它指的是“约束上的唯一约束失败”并提到了
itemsId
。从架构来看,这显然是Rank.itemsId
。
Rank.itemsId
是引用 Items.id
的外键。因此,当输入新行数据时,该值应该是现有 item
的 id。你的模式中奇怪的是:
model Rank {
/// ...
Items Items? @relation(fields: [itemsId], references: [id], onDelete: Cascade)
itemsId Int @id
}
如文档中所解释:
和:
@id
在模型上定义单字段 ID。
[解决方案
@id
] 无法在关系字段上定义
@id
中删除
Rank.itemsId
属性。我不知道为什么在不支持这种情况的情况下创建数据库模式甚至会成功。