我的 SQLite Prisma 架构是否针对多对多关系正确设置?我在使用 Prisma Studio 设置虚拟用户时遇到错误

问题描述 投票:0回答:1

这是我第一次使用后端,在本例中,我在 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 },
    })
}

sqlite prisma next.js13
1个回答
0
投票

问题

花了一段时间才理解您想要实现的目标,但现在我相当有信心可以回答您的问题。让我尝试写下我是如何理解这个场景的:

您正在使用 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
 属性。

我不知道为什么在不支持这种情况的情况下创建数据库模式甚至会成功。

© www.soinside.com 2019 - 2024. All rights reserved.