据我所知,这是一个我无法解决的逻辑问题。使用
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,因此关系永远不会被删除。出了什么问题?我错过了什么?
对不起,这太乱了,我希望你能跟上这个疯狂!
我现在可以看到问题的症结所在......在创建
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,
},
}),
),
);
}