如何用Prisma定义关联双用户的Vote类型实现用户打分功能
Hey there! Since you’re coming from Firebase and MongoDB, Prisma’s schema-driven approach will feel intuitive—you’ll still be defining relationships, but with built-in type safety and database-level constraints. Let’s walk through setting up your Vote model step by step.
1. First, Make Sure Your User Model is Defined
Since Vote links two users (the one casting the vote and the one receiving it), you’ll need a base User model first. Here’s a standard example:
model User { id String @id @default(cuid()) // Or use uuid() if you prefer UUIDs name String? email String @unique // Add other User fields you need (like passwordHash, avatarUrl, etc.) // Reverse relationships for votes: votes this user has cast, and votes they've received votesCast Vote[] @relation("VotesFromUser") votesReceived Vote[] @relation("VotesForUser") }
2. Define the Vote Model
Now let’s create the Vote model with your required fields, and set up the relationships to User. Prisma uses the @relation attribute to clarify which reverse relationship maps to each field (since we have two links to User):
model Vote { id String @id @default(cuid()) rate Float @db.Decimal(5,2) // Optional: Use Decimal for precise rating values instead of Float from User @relation("VotesFromUser", fields: [fromUserId], references: [id]) for User @relation("VotesForUser", fields: [forUserId], references: [id]) // Foreign key fields (Prisma will generate these, but we explicitly define them for clarity) fromUserId String forUserId String // Add a unique constraint to prevent duplicate votes from the same user to the same recipient @@unique([fromUserId, forUserId]) }
Key Details to Note:
- Relationship Names: The
@relationnames ("VotesFromUser"and"VotesForUser") are crucial here—they tell Prisma which reverse relationship on theUsermodel corresponds to eachVotefield. Without these, Prisma wouldn’t know how to map the two separateUserlinks. - Unique Constraint: The
@@unique([fromUserId, forUserId])ensures a user can’t vote for the same person more than once, which is probably what you want for a rating system. - Float vs Decimal: If you need precise rating values (like avoiding floating-point inaccuracies), use
@db.Decimal(5,2)instead of plainFloat—this will store the rate as a decimal with 5 total digits and 2 after the decimal (e.g., 4.50, 5.00).
3. How This Compares to Your MongoDB Approach
In MongoDB, you’d create a separate collection with fromUserId and forUserId as ObjectIDs. Prisma does the same under the hood: it creates a Vote table (or collection, if you’re using MongoDB with Prisma!) with foreign key columns linking to the User table/collection. The difference is Prisma handles the relationship logic and type safety for you, so you don’t have to manually manage joins or ID references in your code.
4. Example Query to Create a Vote
Once your schema is set up, you can create a vote using Prisma Client like this:
const newVote = await prisma.vote.create({ data: { rate: 4.5, from: { connect: { id: "user-casting-vote-id" } }, for: { connect: { id: "user-receiving-vote-id" } }, }, include: { from: { select: { name: true } }, for: { select: { name: true } }, }, });
That’s it! This setup will give you a robust, type-safe way to handle user-to-user ratings in Prisma.
内容的提问来源于stack exchange,提问作者Daniil Andreyevich Baunov

