Add Jellyfin mappings and optimize cast queries
Performance and settings updates: - Add a new jellyfin_library_mappings column to the settings table and wire it into the Settings model (update handling and default value). This enables storing Jellyfin library mappings in settings. - Optimize Cast::list by loading all cast filmography in a single joined query and grouping results per cast to avoid N+1 queries. - Remove per-item cast/staff loading in Media model to avoid repeated queries during list/search operations. - Remove game-specific enrichment from MediaController search to stop extra game info lookups during search responses. These changes reduce repeated DB calls and centralize Jellyfin mapping storage.
This commit is contained in:
@@ -279,16 +279,6 @@ class MediaController {
|
|||||||
|
|
||||||
$result = $this->media->search($filters, $page, $limit);
|
$result = $this->media->search($filters, $page, $limit);
|
||||||
|
|
||||||
// Game-spezifische Daten für Games laden
|
|
||||||
foreach ($result['items'] as &$item) {
|
|
||||||
if ($item['type'] === 'Game') {
|
|
||||||
$gameInfo = $this->game->getGameInfoForList($item['id']);
|
|
||||||
if ($gameInfo) {
|
|
||||||
$item = array_merge($item, $gameInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ['success' => true, 'data' => $result];
|
return ['success' => true, 'data' => $result];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -357,6 +357,7 @@ class Database {
|
|||||||
auto_play_trailers BOOLEAN DEFAULT 0,
|
auto_play_trailers BOOLEAN DEFAULT 0,
|
||||||
language TEXT DEFAULT 'en',
|
language TEXT DEFAULT 'en',
|
||||||
theme TEXT DEFAULT 'system',
|
theme TEXT DEFAULT 'system',
|
||||||
|
jellyfin_library_mappings JSON,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -49,16 +49,37 @@ class Cast extends BaseModel {
|
|||||||
$items = $this->findAll($conditions, 'createdAt DESC', $limit, $offset);
|
$items = $this->findAll($conditions, 'createdAt DESC', $limit, $offset);
|
||||||
$total = $this->count($conditions);
|
$total = $this->count($conditions);
|
||||||
|
|
||||||
|
// Load filmography for all cast members in a single query
|
||||||
|
if (!empty($items)) {
|
||||||
|
$castIds = array_column($items, 'id');
|
||||||
|
$placeholders = str_repeat('?,', count($castIds) - 1) . '?';
|
||||||
|
|
||||||
// Add filmography to each cast member
|
$stmt = $this->pdo->prepare("
|
||||||
foreach ($items as &$item) {
|
SELECT mc.cast_id, m.id, m.title, m.year, m.poster, m.category, m.type, mc.role, mc.characterName
|
||||||
$item['filmography'] = $this->getMediaForCast($item['id']);
|
FROM media m
|
||||||
// Extract unique media types
|
INNER JOIN media_cast mc ON m.id = mc.media_id
|
||||||
$mediaTypes = array_unique(array_column($item['filmography'], 'category'));
|
WHERE mc.cast_id IN ($placeholders)
|
||||||
$item['media_types'] = array_values($mediaTypes);
|
ORDER BY m.year DESC
|
||||||
|
");
|
||||||
|
$stmt->execute($castIds);
|
||||||
|
$allFilmography = $stmt->fetchAll();
|
||||||
|
|
||||||
|
// Group filmography by cast_id
|
||||||
|
$filmographyByCast = [];
|
||||||
|
foreach ($allFilmography as $film) {
|
||||||
|
$castId = $film['cast_id'];
|
||||||
|
unset($film['cast_id']);
|
||||||
|
$filmographyByCast[$castId][] = $film;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach filmography to each cast member
|
||||||
|
foreach ($items as &$item) {
|
||||||
|
$item['filmography'] = $filmographyByCast[$item['id']] ?? [];
|
||||||
|
$mediaTypes = array_unique(array_column($item['filmography'], 'category'));
|
||||||
|
$item['media_types'] = array_values($mediaTypes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'items' => $items,
|
'items' => $items,
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
|
|||||||
@@ -65,11 +65,6 @@ class Media extends BaseModel {
|
|||||||
$stmt->execute($params);
|
$stmt->execute($params);
|
||||||
$items = $stmt->fetchAll();
|
$items = $stmt->fetchAll();
|
||||||
|
|
||||||
// Cast-Mitglieder für jedes Medium laden
|
|
||||||
foreach ($items as &$item) {
|
|
||||||
$item['staff'] = $this->getCastForMedia($item['id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count Query
|
// Count Query
|
||||||
$countQuery = "SELECT COUNT(*) FROM {$this->table} WHERE 1=1";
|
$countQuery = "SELECT COUNT(*) FROM {$this->table} WHERE 1=1";
|
||||||
$countParams = [];
|
$countParams = [];
|
||||||
@@ -93,11 +88,6 @@ class Media extends BaseModel {
|
|||||||
} else {
|
} else {
|
||||||
$items = $this->findAll($conditions, 'createdAt DESC', $limit, $offset);
|
$items = $this->findAll($conditions, 'createdAt DESC', $limit, $offset);
|
||||||
$total = $this->count($conditions);
|
$total = $this->count($conditions);
|
||||||
|
|
||||||
// Cast-Mitglieder für jedes Medium laden
|
|
||||||
foreach ($items as &$item) {
|
|
||||||
$item['staff'] = $this->getCastForMedia($item['id']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ class Settings extends BaseModel {
|
|||||||
$updateData['theme'] = $data['theme'];
|
$updateData['theme'] = $data['theme'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($data['jellyfin_library_mappings'])) {
|
||||||
|
$updateData['jellyfin_library_mappings'] = $data['jellyfin_library_mappings'];
|
||||||
|
}
|
||||||
|
|
||||||
// Check if settings row exists
|
// Check if settings row exists
|
||||||
$existing = $this->findById(1);
|
$existing = $this->findById(1);
|
||||||
|
|
||||||
@@ -72,7 +76,7 @@ class Settings extends BaseModel {
|
|||||||
'auto_play_trailers' => 0,
|
'auto_play_trailers' => 0,
|
||||||
'language' => 'en',
|
'language' => 'en',
|
||||||
'theme' => 'system',
|
'theme' => 'system',
|
||||||
'theme' => 'system'
|
'jellyfin_library_mappings' => ''
|
||||||
];
|
];
|
||||||
$mergedData = array_merge($defaultData, $updateData);
|
$mergedData = array_merge($defaultData, $updateData);
|
||||||
$this->create($mergedData);
|
$this->create($mergedData);
|
||||||
|
|||||||
Reference in New Issue
Block a user