无法使用 Prisma 和 Javascript 在两个数据库表之间创建关系逻辑

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

据我所知,这是一个我无法解决的逻辑问题。使用

next-connect
我有一个更新数据库中条目的功能:

  .put(async (req, res) => {
    const data = req.body;
    const { dob, roles, cases } = data ?? {};
    const convertedDob = dob ? new Date(dob) : null;

    const roleIds = roles?.map((role: Role) => {
      return { id: role.id };
    });

    const caseIds = cases?.map((_case: Case) => {
      return { id: _case.id };
    });

    data.dob = convertedDob;
    delete data.roles;
    delete data.formData;

    const user = await getUserDataFromSession(req, res);
    throwIfNoCurrentTeam(user?.currentTeam);

    try {
      const person: Person = await prisma.person.update({
        where: { id: data.id },
        data: {
          ...data,
          roles: { connect: roleIds },
          cases: { connect: caseIds },
        },
      });

      if (person && person.linkedIds) {
        // get linkedId arrays of all people linked to this person
        const associatedPeopleIdArrays = await prisma.$transaction(
          person.linkedIds.map((id) =>
            prisma.person.findUnique({
              where: { id },
              select: { id: true, linkedIds: true },
            }),
          ),
        );

        const backLinkArray = associatedPeopleIdArrays.map((linkedPerson) => {
          const linkedPersonIds = linkedPerson?.linkedIds;
          const linkedPersonOwnId = linkedPerson?.id;

          // if the array of linkedIds already includes the person we are back-linking, enter next check
          if (linkedPersonIds?.includes(person.id)) {
            // if they both include each other, do nothing
            if (person.linkedIds.includes(linkedPersonOwnId as string)) {
              return { id: linkedPersonOwnId, linkedIds: linkedPersonIds };
            }
            // if linkedPersonIds includes person.id but person.linkedIds does not include linkedPersonOwnId, remove the relationship
            return { id: linkedPersonOwnId, linkedIds: linkedPersonIds.filter((id) => id !== person.id) };
            // else add the current person's id to each person's array that we are back-linking
          } else {
            return {
              id: linkedPersonOwnId,
              linkedIds: linkedPersonIds ? [...linkedPersonIds, person.id] : [person.id],
            };
          }
        });

        // write the new linkedId array to each associated person
        await prisma.$transaction(
          backLinkArray.map((linkedPerson) =>
            prisma.person.update({
              where: { id: linkedPerson?.id },
              data: {
                linkedIds: linkedPerson?.linkedIds,
              },
            }),
          ),
        );
      }

      return res.status(200).json({ updated: person });
    } catch (err: any) {
      console.log({ err });
      handleApiError('Failed to update person', 500, err);
    }
  });

我已经留下评论来尝试跟踪我留下的正在发生的事情,以防它们有助于理解我正在尝试做的事情。我已经在各处创建日志以查看发生了什么,但问题确实出在 if/else 逻辑中。

函数正常工作,建立两个人之间的关系。如果一个

id
被添加到一个人的
linkedIds
数组中,那么那个人的
id
也被添加到关联的人的数组中。

但是如果从一个人的

id
中删除
linkedIds
,我需要额外的逻辑来删除关系,这就是它崩溃的地方。目前逻辑似乎正确地输入了这个 if 语句:
if (linkedPersonIds?.includes(person.id))
,但随后它 always 输入以下 if 语句:
if (person.linkedIds.includes(linkedPersonOwnId as string))
.

我希望如果从

linkedIds
数组中删除一个人,那么该语句将返回 false,但事实并非如此。它每次都返回 true,因此关系永远不会被删除。出了什么问题?我错过了什么?

对不起,这太乱了,我希望你能跟上这个疯狂!

typescript prisma next next-connect
1个回答
0
投票

我现在可以看到问题的症结所在......在创建

associatedPeopleArrays
时它不会将最近删除的
id
添加到
backLinkArray
这意味着永远不会检查那个
id
!

所以我需要做的是在更新之前获取以前版本的

linkedIds
数组,这意味着在前端进行更改以确保它与更新的数据一起发送。

这样我就可以比较旧的

linkedIds
和新的
linkedIds
,找出不同之处。我确定我的代码冗长冗长,但这是我的解决方案并且有效!

      if (person?.linkedIds || initialLinkedIds) {

        // ADD RELATIONSHIPS
        // get linkedId arrays of all people newly linked to this person
        const newlyAssociatedPeopleIdArrays = await prisma.$transaction(
          person.linkedIds.map((id: string) =>
            prisma.person.findUnique({
              where: { id },
              select: { id: true, linkedIds: true },
            }),
          ),
        );

        // populate the associated peoples' arrays with the person that just added them
        const addRelationshipArray = newlyAssociatedPeopleIdArrays?.map((linkedPerson) => {
          const linkedPersonIds = linkedPerson?.linkedIds;
          const linkedPersonOwnId = linkedPerson?.id;

          if (!linkedPersonIds?.includes(person.id)) {
            return { id: linkedPersonOwnId, linkedIds: [...linkedPersonIds, person.id] };
          }

          return linkedPerson;
        });

        // REMOVE RELATIONSHIPS
        // get the difference between the old linkedIds and the current linkedIds
        const removedIds = initialLinkedIds.filter((id: string) => !person.linkedIds.includes(id));

        // get the linkedId arrays for each id that has been removed
        const newlyRemovedPeopleIdArrays = await prisma.$transaction(
          removedIds.map((id: string) =>
            prisma.person.findUnique({
              where: { id },
              select: { id: true, linkedIds: true },
            }),
          ),
        );

        // map over those linkedId arrays and remove the current person
        const removeRelationshipArray = newlyRemovedPeopleIdArrays.map((unlinkedPerson) => ({
          ...unlinkedPerson,
          linkedIds: unlinkedPerson.linkedIds.filter((id: string) => id !== person.id),
        }));

        // combine the two relationship arrays
        const combinedUpdateArray = [...removeRelationshipArray, ...addRelationshipArray];

        // write these new arrays to the database
        await prisma.$transaction(
          combinedUpdateArray.map((linkedPerson) =>
            prisma.person.update({
              where: { id: linkedPerson?.id },
              data: {
                linkedIds: linkedPerson?.linkedIds,
              },
            }),
          ),
        );
      }
© www.soinside.com 2019 - 2024. All rights reserved.