Refactor relationship loading in FalukantService: Update logic to load relationships without eager loading, preventing EagerLoadingError. Enhance data retrieval by using separate queries for traits and moods, improving performance and reliability.

This commit is contained in:
Torsten Schulz (local)
2026-02-04 15:12:36 +01:00
parent 0697f3d363
commit 057b038fac

View File

@@ -2638,38 +2638,69 @@ class FalukantService extends BaseService {
if (!user) throw new Error('User not found'); if (!user) throw new Error('User not found');
const character = await FalukantCharacter.findOne({ where: { userId: user.id } }); const character = await FalukantCharacter.findOne({ where: { userId: user.id } });
if (!character) throw new Error('Character not found for this user'); if (!character) throw new Error('Character not found for this user');
let relationships = await Relationship.findAll({ // Load relationships without includes to avoid EagerLoadingError
const relRows = await Relationship.findAll({
where: { character1Id: character.id }, where: { character1Id: character.id },
attributes: ['createdAt', 'widowFirstName2', 'nextStepProgress'], attributes: ['createdAt', 'widowFirstName2', 'nextStepProgress', 'character2Id', 'relationshipTypeId']
include: [ });
{ let relationships;
model: FalukantCharacter, as: 'character2', if (relRows.length === 0) {
relationships = [];
} else {
const typeIds = [...new Set(relRows.map(r => r.relationshipTypeId))];
const char2Ids = relRows.map(r => r.character2Id);
const [types, character2s] = await Promise.all([
RelationshipType.findAll({ where: { id: typeIds }, attributes: ['id', 'tr'] }),
FalukantCharacter.findAll({
where: { id: char2Ids },
attributes: ['id', 'birthdate', 'gender', 'moodId'], attributes: ['id', 'birthdate', 'gender', 'moodId'],
include: [ include: [
{ model: FalukantPredefineFirstname, as: 'definedFirstName', attributes: ['name'] }, { model: FalukantPredefineFirstname, as: 'definedFirstName', attributes: ['name'] },
{ model: TitleOfNobility, as: 'nobleTitle', attributes: ['labelTr'] }, { model: TitleOfNobility, as: 'nobleTitle', attributes: ['labelTr'] },
{ model: CharacterTrait, as: 'traits' }, { model: Mood, as: 'mood' }
{ model: Mood, as: 'mood' },
]
},
{ model: RelationshipType, as: 'relationshipType', attributes: ['tr'] }
] ]
})
]);
const typeMap = Object.fromEntries(types.map(t => [t.id, t]));
const char2Map = Object.fromEntries(character2s.map(c => [c.id, c]));
const ctRows = await FalukantCharacterTrait.findAll({
where: { characterId: char2Ids },
attributes: ['characterId', 'traitId']
}); });
relationships = relationships.map(r => ({ const allTraitIds = [...new Set(ctRows.map(r => r.traitId))];
const traitsList = allTraitIds.length
? await CharacterTrait.findAll({ where: { id: allTraitIds }, attributes: ['id', 'tr'] })
: [];
const traitMap = Object.fromEntries(traitsList.map(t => [t.id, t]));
const traitsByChar = {};
for (const row of ctRows) {
if (!traitsByChar[row.characterId]) traitsByChar[row.characterId] = [];
const t = traitMap[row.traitId];
if (t) traitsByChar[row.characterId].push(t);
}
for (const c of character2s) {
c.setDataValue('traits', traitsByChar[c.id] || []);
}
const relationships = relRows.map(r => {
const c2 = char2Map[r.character2Id];
const type = typeMap[r.relationshipTypeId];
return {
createdAt: r.createdAt, createdAt: r.createdAt,
widowFirstName2: r.widowFirstName2, widowFirstName2: r.widowFirstName2,
progress: r.nextStepProgress, progress: r.nextStepProgress,
character2: { character2: c2 ? {
id: r.character2.id, id: c2.id,
age: calcAge(r.character2.birthdate), age: calcAge(c2.birthdate),
gender: r.character2.gender, gender: c2.gender,
firstName: r.character2.definedFirstName?.name || 'Unknown', firstName: c2.definedFirstName?.name || 'Unknown',
nobleTitle: r.character2.nobleTitle?.labelTr || '', nobleTitle: c2.nobleTitle?.labelTr || '',
mood: r.character2.mood, mood: c2.mood,
traits: r.character2.traits traits: c2.traits || []
}, } : null,
relationshipType: r.relationshipType.tr relationshipType: type ? type.tr : ''
})); };
});
}
const charsWithChildren = await FalukantCharacter.findAll({ const charsWithChildren = await FalukantCharacter.findAll({
where: { userId: user.id }, where: { userId: user.id },
include: [ include: [
@@ -2927,7 +2958,7 @@ class FalukantService extends BaseService {
const myChar = user.character; const myChar = user.character;
if (!myChar) throw new Error('Character not found'); if (!myChar) throw new Error('Character not found');
// 2) Beziehung finden und „anderen“ Character bestimmen // 2) Beziehung finden und „anderen“ Character bestimmen (ohne Include, um EagerLoadingError zu vermeiden)
const rel = await Relationship.findOne({ const rel = await Relationship.findOne({
where: { where: {
[Op.or]: [ [Op.or]: [
@@ -2935,14 +2966,25 @@ class FalukantService extends BaseService {
{ character2Id: myChar.id } { character2Id: myChar.id }
] ]
}, },
include: [ attributes: ['character1Id', 'character2Id']
{ model: FalukantCharacter, as: 'character1', include: [{ model: CharacterTrait, as: 'traits' }] },
{ model: FalukantCharacter, as: 'character2', include: [{ model: CharacterTrait, as: 'traits' }] }
]
}); });
if (!rel) throw new Error('Beziehung nicht gefunden'); if (!rel) throw new Error('Beziehung nicht gefunden');
const relatedChar = rel.character1.id === myChar.id ? rel.character2 : rel.character1; const relatedCharId = rel.character1Id === myChar.id ? rel.character2Id : rel.character1Id;
const relatedChar = await FalukantCharacter.findOne({
where: { id: relatedCharId },
attributes: ['id', 'moodId']
});
if (!relatedChar) throw new Error('Related character not found');
const ctRows = await FalukantCharacterTrait.findAll({
where: { characterId: relatedCharId },
attributes: ['traitId']
});
const traitIds = ctRows.map(r => r.traitId);
const traits = traitIds.length
? await CharacterTrait.findAll({ where: { id: traitIds }, attributes: ['id'] })
: [];
relatedChar.setDataValue('traits', traits);
// 3) Trait-IDs und Mood des relatedChar // 3) Trait-IDs und Mood des relatedChar
const relatedTraitIds = relatedChar.traits.map(t => t.id); const relatedTraitIds = relatedChar.traits.map(t => t.id);