prioritize results by word match
This commit is contained in:
56
server.js
56
server.js
@ -2,41 +2,75 @@ const express = require('express');
|
|||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
const cinecheck = require('./aggregators/cinecheck-adapter');
|
const cinecheck = require('./aggregators/cinecheck-adapter');
|
||||||
const commonsense = require('./aggregators/commonsense-adapter');
|
const commonsense = require('./aggregators/commonsense-adapter');
|
||||||
const filmages = require('./aggregators/filmages-adapter'); // New
|
const filmages = require('./aggregators/filmages-adapter');
|
||||||
const { mergeResults } = require('./merge');
|
const { mergeResults } = require('./merge');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
|
|
||||||
|
// Helper to normalize text and get words for matching
|
||||||
|
function getWords(text) {
|
||||||
|
if (!text || typeof text !== 'string') return [];
|
||||||
|
return text
|
||||||
|
.toLowerCase()
|
||||||
|
// Remove punctuation, keep letters, numbers, and whitespace. Handles Unicode.
|
||||||
|
.replace(/[^\p{L}\p{N}\s]/gu, '')
|
||||||
|
.replace(/\s+/g, ' ') // Normalize multiple spaces to single
|
||||||
|
.trim()
|
||||||
|
.split(' ')
|
||||||
|
.filter(Boolean); // Remove empty strings from split
|
||||||
|
}
|
||||||
|
|
||||||
app.get('/search', async (req, res) => {
|
app.get('/search', async (req, res) => {
|
||||||
const q = req.query.q;
|
const q = req.query.q;
|
||||||
if (!q) {
|
if (!q) {
|
||||||
// Gilfoyle: "A search query without a query. Bold."
|
return res.status(400).json({ error: "Missing query. Predictable." });
|
||||||
return res.status(400).json({ error: "Missing query. Astounding." });
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Mike: "Run 'em all. See what sticks."
|
|
||||||
const [cine, cs, fa] = await Promise.all([
|
const [cine, cs, fa] = await Promise.all([
|
||||||
cinecheck.searchAndEnrich(q).catch(e => { console.error('Cinecheck failed:', e.message); return []; }),
|
cinecheck.searchAndEnrich(q).catch(e => { console.error('Cinecheck failed:', e.message); return []; }),
|
||||||
commonsense.searchAndEnrich(q).catch(e => { console.error('Commonsense failed:', e.message); return []; }),
|
commonsense.searchAndEnrich(q).catch(e => { console.error('Commonsense failed:', e.message); return []; }),
|
||||||
filmages.searchAndEnrich(q).catch(e => { console.error('Filmages failed:', e.message); return []; })
|
filmages.searchAndEnrich(q).catch(e => { console.error('Filmages failed:', e.message); return []; })
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!cine.length && !cs.length && !fa.length) {
|
let merged = mergeResults([cine, cs, fa]);
|
||||||
// Gilfoyle: "Zero results. Is this a surprise to anyone?"
|
|
||||||
|
// Sort merged results based on query relevance
|
||||||
|
const queryWords = getWords(q);
|
||||||
|
if (queryWords.length > 0) {
|
||||||
|
merged.forEach(item => {
|
||||||
|
const titleWords = getWords(item.title);
|
||||||
|
const uniqueQueryWords = [...new Set(queryWords)];
|
||||||
|
const uniqueTitleWords = [...new Set(titleWords)];
|
||||||
|
|
||||||
|
let commonWordCount = 0;
|
||||||
|
for (const qw of uniqueQueryWords) {
|
||||||
|
if (uniqueTitleWords.includes(qw)) {
|
||||||
|
commonWordCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.matchScore1 = uniqueQueryWords.length > 0 ? commonWordCount / uniqueQueryWords.length : 0;
|
||||||
|
|
||||||
|
const unionLength = new Set([...uniqueQueryWords, ...uniqueTitleWords]).size;
|
||||||
|
item.matchScore2 = unionLength > 0 ? commonWordCount / unionLength : 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
merged.sort((a, b) => {
|
||||||
|
if (b.matchScore1 !== a.matchScore1) return b.matchScore1 - a.matchScore1;
|
||||||
|
if (b.matchScore2 !== a.matchScore2) return b.matchScore2 - a.matchScore2;
|
||||||
|
return getWords(a.title).length - getWords(b.title).length; // Shorter titles preferred as tertiary sort
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const merged = mergeResults([cine, cs, fa]);
|
|
||||||
res.json(merged);
|
res.json(merged);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Mike: "Something went sideways. Happens."
|
|
||||||
console.error('General search error:', e);
|
console.error('General search error:', e);
|
||||||
res.status(500).json({ error: e.message || "Server had a moment." });
|
res.status(500).json({ error: e.message || "Server's taking a nap." });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const PORT = 3000;
|
const PORT = 3000;
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
// Gilfoyle: "It's listening. Don't get excited."
|
console.log(`Backend sorting your life out on http://localhost:${PORT}. You're welcome.`);
|
||||||
console.log(`Backend multi-agrégateurs opérationnel sur http://localhost:${PORT}. Ne me remerciez pas.`);
|
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user