我想制作一个聊天应用程序,可以做到:
用户可以发送/接收好友请求
当用户1向用户2发送好友请求时,如果用户2
棱镜模式:
model User {
id String @id @default(cuid())
username String? @unique
password String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
sentFriendRequests Friend[] @relation("SentFriendRequests")
receivedFriendRequests Friend[] @relation("ReceivedFriendRequests")
friends Friend[]
}
model Friend {
id String @id @default(cuid())
User User? @relation(fields: [userId], references: [id])
userId String?
requester User? @relation("SentFriendRequests", fields: [requesterId], references:
[id])
receiver User? @relation("ReceivedFriendRequests", fields: [receiverId],
references: [id])
requesterId String?
receiverId String?
@@unique([requesterId, receiverId])
}
我使用了 nextjs 13 API 路由来接受好友请求 API:
import { db } from "@/lib/db";
import { FriendRequest } from "@/types/chatTypes";
import { NextRequest, NextResponse } from "next/server";
import { ZodError } from "zod";
export async function POST(req: NextRequest) {
const data = await req.json();
try {
// valiadting user input
const validatedData = FriendRequest.parse(data);
const { receiverId, requesterId } = validatedData;
// checking if user exists or not
const requester = await db.user.findUnique({
where: { id: requesterId },
});
const receiver = await db.user.findUnique({
where: { id: receiverId },
});
if (!requester || !receiver) {
return NextResponse.json({ message: "User not Found" }, { status: 404 });
}
await db.$transaction([
// Add each other to friends array
db.user.update({
where: { id: receiverId },
data: { friends: { connect: { id: requesterId } } },
}),
db.user.update({
where: { id: requesterId },
data: { friends: { connect: { id: receiverId } } },
}),
// Remove from receivedFriendRequests and sentFriendRequests
db.friend.delete({
where: {
requesterId_receiverId: {
requesterId: requesterId,
receiverId: receiverId,
},
},
}),
]);
return NextResponse.json(
{ message: "Friend Request Accepted Successfully" },
{ status: 201 }
);
} catch (error) {
// Handling Validation error using zod
if (error instanceof ZodError) {
return NextResponse.json(
{ message: error.flatten().fieldErrors },
{ status: 400 }
);
}
return NextResponse.json(
{ message: `Something bad happened, Try again : ${error}` },
{ status: 400 }
);
}
}
我知道这段代码是错误的,因为 id 与接收者或 requesterid 都不匹配,并给出此错误:
{
"message": "Something bad happened, Try again : PrismaClientKnownRequestError:
\nInvalid `prisma.user.update()` invocation:\n\n\nThe required connected records were
not found. Expected 1 records to be connected after connect operation on one-to-many
relation 'FriendToUser', found 0."
}
如何解决这个问题?谁能帮我解决这个问题吗?
在您的架构中,用户的表上没有直接的朋友数组。相反,它表示为与“朋友”表的一对多关系。这意味着您不会删除好友记录;当好友请求被接受或拒绝时,通过更新“好友”表中的状态字段,将其从用户的表中“删除”。
此外,无需手动检查 API 路由中是否存在 ID,因为数据库已经处理了该验证,如果发生错误,您可以捕获错误,从而减少不必要的查询。此外,在这种情况下,您不需要手动发起交易,因为 Prisma 会自动为您管理交易。
此外,必须使用枚举向“Friends”表添加状态字段,确保一致性并为不同的好友状态提供预定义值(例如,PENDING、ACCEPTED、DECLINED)。您还需要将状态发送到 API 路由。
model User {
id String @id @default(cuid())
username String? @unique
password String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
sentFriendRequests Friend[] @relation("SentFriendRequests", references: [id])
receivedFriendRequests Friend[] @relation("ReceivedFriendRequests", references: [id])
friends Friend[] @relation("Friends", references: [id])
}
model Friend {
id String @id @default(cuid())
sender User? @relation("SentFriendRequests", fields: [senderId], references: [id])
senderId String?
receiver User? @relation("ReceivedFriendRequests", fields: [receiverId], references: [id])
receiverId String?
status FriendRequestStatus @default(PENDING)// Define FriendRequestStatus enum & set to pending by default
@@unique([senderId, receiverId])
}
enum FriendRequestStatus {
PENDING
ACCEPTED
DECLINED
}
export async function POST(req: NextRequest) {
try {
const data = await req.json();
const validatedData = FriendRequest.parse(data);
const { receiverId, requesterId, status } = validatedData;
// Update the friend request status, works for accept & reject
await prisma.friend.update({
where: { receiverId, requesterId },
data: { status },
});
return NextResponse.json({ message: `Friend request ${status === "ACCEPTED" ? "accepted" : "rejected" }.`}, { status: 201 });
} catch (error) {
// Handling Validation error using zod
if (error instanceof ZodError) {
return NextResponse.json({ message: error.flatten().fieldErrors }, { status: 400 });
}
if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === "P2025") {
// User not found error
return NextResponse.json({ message: "User not Found" },{ status: 404 });
}
} else {
return NextResponse.json({ message: "Unexpected error occurred" }, { status: 500 });
}
}
}
await prisma.friend.create({
data: { senderId: "YOUR_SENDER_ID", receiverId: "YOUR_RECIEVER_ID" } // don't need to set status here bc it defaults to pending in the DB
});
const sentFriendRequests = await prisma.friend.findMany({
where: {
senderId: "YOUR_USER_ID", // Replace with the actual user's ID
status: "PENDING", // Assuming you want to retrieve pending sent requests
},
select: {
receiver: true, // This selects the receiver (the recipient of the request)
},
});
const pendingFriendRequests = await prisma.friend.findMany({
where: {
receiverId: "YOUR_USER_ID", // Replace with the actual user's ID
status: "PENDING",
},
});
const acceptedFriends = await prisma.friend.findMany({
where: {
senderId: "YOUR_USER_ID", // Replace with the actual user's ID
status: "ACCEPTED",
},
select: {
receiver: true, // This selects the receiver (your friend)
},
});