Files
noctune-server/src/controllers/searchController.js
T

75 lines
1.9 KiB
JavaScript

import mongoose from 'mongoose';
import Track from '../models/Track.js';
export const searchController = {
async search(req, res, next) {
try {
const query = (req.query.q || '').trim();
if (!query) {
return res.json({
success: true,
data: { tracks: [], artists: [], albums: [] },
});
}
const regex = new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
const tracks = await Track.find({
$or: [
{ title: regex },
{ artist: regex },
{ album: regex },
],
})
.select('-__v')
.sort({ createdAt: -1 })
.limit(50)
.lean();
const artistMap = new Map();
tracks.forEach(t => {
if (!artistMap.has(t.artist)) {
artistMap.set(t.artist, {
_id: new mongoose.Types.ObjectId(),
name: t.artist,
imageUrl: t.coverUrl || '',
trackCount: 0,
});
}
const entry = artistMap.get(t.artist);
entry.trackCount++;
if (t.coverUrl && !entry.imageUrl) {
entry.imageUrl = t.coverUrl;
}
});
const artists = [...artistMap.values()];
const albumMap = new Map();
tracks.forEach(t => {
if (!albumMap.has(t.album)) {
albumMap.set(t.album, {
_id: new mongoose.Types.ObjectId(),
title: t.album,
artist: t.artist,
coverUrl: t.coverUrl || '',
trackCount: 0,
});
}
const entry = albumMap.get(t.album);
entry.trackCount++;
if (t.coverUrl && !entry.coverUrl) {
entry.coverUrl = t.coverUrl;
}
});
const albums = [...albumMap.values()];
const data = { tracks, artists, albums };
return res.json({ success: true, data });
} catch (error) {
return next(error);
}
},
};