如何更新prisma中的多对多关系?

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

我想制作一个聊天应用程序,可以做到:

  • 用户可以发送/接收好友请求

  • 当用户1向用户2发送好友请求时,如果用户2

    • 接受请求:user2 和 user1 的好友数组将相互包含
      user1 的 sentFriendRequest 数组将删除 user2 详细信息
      类似地,user2 的 receiveFriendRequest 将删除 用户1详情
    • 拒绝请求:像上面这样的所有内容,只是两个用户的朋友都将包括 什么都没有

    棱镜模式:

    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."
}

如何解决这个问题?谁能帮我解决这个问题吗?

javascript next.js prisma
1个回答
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)
  },
});
© www.soinside.com 2019 - 2024. All rights reserved.