diff --git a/src/routes/feed.js b/src/routes/feed.js index 622bfd4..ec40336 100644 --- a/src/routes/feed.js +++ b/src/routes/feed.js @@ -88,7 +88,6 @@ router.get('/', requireJwt, async (req, res, next) => { // 6. Resolve UUIDs → words (direct) or via objects→words const placeholderMap = {}; // uuid → { de, en, sv } - const wordObjectMap = {}; // wordId → objectId (for picture lookup) if (uuidArr.length) { // Direct word lookup const wordRes = await query( @@ -125,16 +124,6 @@ router.get('/', requireJwt, async (req, res, next) => { }); } - // For word-type placeholders: find linked objects so we can load their pictures - const wordUuids = uuidArr.filter(u => placeholderMap[u]?.type === 'word'); - if (wordUuids.length) { - const wObjRes = await query( - `SELECT DISTINCT ON (ow.word_id) ow.word_id, ow.object_id - FROM object_words ow WHERE ow.word_id = ANY($1)`, - [wordUuids] - ); - wObjRes.rows.forEach(r => { wordObjectMap[r.word_id] = r.object_id; }); - } } // 7. Fetch statement→word links (positive + negative) @@ -159,52 +148,25 @@ router.get('/', requireJwt, async (req, res, next) => { negRes.rows.forEach(r => { statWordMap[r.statement_id]?.negative.push({ id: r.id, de: r.de, en: r.en, sv: r.sv }); }); } - // 8. Find pictures: via objects referenced in sentences, or via object_pairs - const objectUuids = uuidArr.filter(u => !Object.values(questionsMap).concat(Object.values(statementsMap)) - .flatMap(x => [x.sentence_de || '', x.positive_sentence_de || '']) - .some(s => s.includes(u) && placeholderMap[u]) - ? false : placeholderMap[u] !== undefined - ); - - // Simpler: collect all object-UUIDs (those resolved via object_words) - const resolvedObjectIds = new Set(); - if (uuidArr.length) { - const objCheckRes = await query( - `SELECT DISTINCT object_id AS id FROM object_words WHERE object_id = ANY($1)`, - [uuidArr] - ); - objCheckRes.rows.forEach(r => resolvedObjectIds.add(r.id)); - } - // Also include objects linked to word-type placeholders - Object.values(wordObjectMap).forEach(oid => resolvedObjectIds.add(oid)); - - const pictureMap = {}; // objectId → { url, blurhash } - if (resolvedObjectIds.size) { + // 8. Find pictures via object_pairs (direct pair → object link) + const pairIds = pairs.map(p => p.id); + const pairPictureMap = {}; // pairId → { url, blurhash } + if (pairIds.length) { const picRes = await query( - `SELECT DISTINCT ON (op.object_id) - op.object_id, p.picture_link AS url, p.blurhash - FROM object_pictures op + `SELECT DISTINCT ON (op2.pair_id) + op2.pair_id, p.picture_link AS url, p.blurhash + FROM object_pairs op2 + JOIN object_pictures op ON op.object_id = op2.object_id JOIN pictures p ON p.id = op.picture_id - WHERE op.object_id = ANY($1) - ORDER BY op.object_id, p.created_at`, - [[...resolvedObjectIds]] + WHERE op2.pair_id = ANY($1) + ORDER BY op2.pair_id, p.created_at`, + [pairIds] ); picRes.rows.forEach(r => { - pictureMap[r.object_id] = { url: r.url, blurhash: r.blurhash }; + pairPictureMap[r.pair_id] = { url: r.url, blurhash: r.blurhash }; }); } - // Pick first available picture across all placeholders in the pair - // Checks both direct object UUIDs and word-type UUIDs linked to objects - function pickPicture(pairUuids) { - for (const u of pairUuids) { - if (pictureMap[u]) return pictureMap[u]; - const oid = wordObjectMap[u]; - if (oid && pictureMap[oid]) return pictureMap[oid]; - } - return null; - } - function buildStatement(id) { if (!id || !statementsMap[id]) return null; const s = statementsMap[id]; @@ -247,7 +209,7 @@ router.get('/', requireJwt, async (req, res, next) => { question: buildQuestion(p.question_id), positive_statement: buildStatement(p.positive_statement_id), negative_statement: buildStatement(p.negative_statement_id), - picture: pickPicture(pairUuids), + picture: pairPictureMap[p.id] || null, placeholders: Object.fromEntries(pairUuids.map(u => [u, placeholderMap[u] || null])), }; });