mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-11-07 15:23:12 -05:00
For API call /Items/{item id} GetBaseItemDto will return the counts of related items e.g. artists, albums, songs. GetBaseItemDto currently does this by calling GetTaggedItems which retrieves the objects into memory to count them. Replace with SQL count.
Fixes:
This should be an improvement for any large libraries, but especially large music libraries. Example:
Request Library -> Genres -> any very popular genre in your large library, e.g. Classical
Number of albums = 1552, songs = 23515, ...
- Before change: Try to retrieve 1552 albums, 23515 songs, ... in memory, API never returns, database on fire
- After change: API returns in 367ms and Genre view opens with 200 albums in 2 seconds
I verified the numbers returned are correct but note that there is a bug somewhere else in Jellyfin that is setting TopParentId to NULL for a large portion of my MusicArtists, which causes them to not be counted by the existing GetCount(). This is not related to this change, also happens with the existing code, and does not seem to affect the Web UI.
Includes Cory's changes in:
- https://github.com/jellyfin/jellyfin/pull/14610#issuecomment-3172211468
- https://github.com/jellyfin/jellyfin/pull/14610#issuecomment-3172239154
163 lines
5.0 KiB
C#
163 lines
5.0 KiB
C#
#nullable disable
|
|
|
|
#pragma warning disable CS1591
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text.Json.Serialization;
|
|
using Jellyfin.Data.Enums;
|
|
using Jellyfin.Extensions;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace MediaBrowser.Controller.Entities
|
|
{
|
|
/// <summary>
|
|
/// Class Studio.
|
|
/// </summary>
|
|
[Common.RequiresSourceSerialisation]
|
|
public class Studio : BaseItem, IItemByName
|
|
{
|
|
/// <summary>
|
|
/// Gets the folder containing the item.
|
|
/// If the item is a folder, it returns the folder itself.
|
|
/// </summary>
|
|
/// <value>The containing folder path.</value>
|
|
[JsonIgnore]
|
|
public override string ContainingFolderPath => Path;
|
|
|
|
[JsonIgnore]
|
|
public override bool IsDisplayedAsFolder => true;
|
|
|
|
[JsonIgnore]
|
|
public override bool SupportsAncestors => false;
|
|
|
|
[JsonIgnore]
|
|
public override bool SupportsPeople => false;
|
|
|
|
public override List<string> GetUserDataKeys()
|
|
{
|
|
var list = base.GetUserDataKeys();
|
|
|
|
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
|
|
return list;
|
|
}
|
|
|
|
public override string CreatePresentationUniqueKey()
|
|
{
|
|
return GetUserDataKeys()[0];
|
|
}
|
|
|
|
public override double GetDefaultPrimaryImageAspectRatio()
|
|
{
|
|
double value = 16;
|
|
value /= 9;
|
|
|
|
return value;
|
|
}
|
|
|
|
public override bool CanDelete()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public override bool IsSaveLocalMetadataEnabled()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
|
{
|
|
query.StudioIds = new[] { Id };
|
|
|
|
return LibraryManager.GetItemList(query);
|
|
}
|
|
|
|
public TaggedItemCounts GetTaggedItemCounts(InternalItemsQuery query)
|
|
{
|
|
query.StudioIds = [Id];
|
|
|
|
var counts = new TaggedItemCounts();
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.MusicAlbum];
|
|
counts.AlbumCount = LibraryManager.GetCount(query);
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.MusicArtist];
|
|
counts.ArtistCount = LibraryManager.GetCount(query);
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.Episode];
|
|
counts.EpisodeCount = LibraryManager.GetCount(query);
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.Movie];
|
|
counts.MovieCount = LibraryManager.GetCount(query);
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.MusicVideo];
|
|
counts.MusicVideoCount = LibraryManager.GetCount(query);
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.LiveTvProgram];
|
|
counts.ProgramCount = LibraryManager.GetCount(query);
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.Series];
|
|
counts.SeriesCount = LibraryManager.GetCount(query);
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.Audio];
|
|
counts.SongCount = LibraryManager.GetCount(query);
|
|
|
|
query.IncludeItemTypes = [BaseItemKind.Trailer];
|
|
counts.TrailerCount = LibraryManager.GetCount(query);
|
|
|
|
return counts;
|
|
}
|
|
|
|
public static string GetPath(string name)
|
|
{
|
|
return GetPath(name, true);
|
|
}
|
|
|
|
public static string GetPath(string name, bool normalizeName)
|
|
{
|
|
// Trim the period at the end because windows will have a hard time with that
|
|
var validName = normalizeName ?
|
|
FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
|
|
name;
|
|
|
|
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.StudioPath, validName);
|
|
}
|
|
|
|
private string GetRebasedPath()
|
|
{
|
|
return GetPath(System.IO.Path.GetFileName(Path), false);
|
|
}
|
|
|
|
public override bool RequiresRefresh()
|
|
{
|
|
var newPath = GetRebasedPath();
|
|
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
|
{
|
|
Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
|
|
return true;
|
|
}
|
|
|
|
return base.RequiresRefresh();
|
|
}
|
|
|
|
/// <summary>
|
|
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
|
|
/// </summary>
|
|
/// <param name="replaceAllMetadata"><c>true</c> to replace all metadata, <c>false</c> to not.</param>
|
|
/// <returns><c>true</c> if changes were made, <c>false</c> if not.</returns>
|
|
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
|
|
{
|
|
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
|
|
|
|
var newPath = GetRebasedPath();
|
|
if (!string.Equals(Path, newPath, StringComparison.Ordinal))
|
|
{
|
|
Path = newPath;
|
|
hasChanges = true;
|
|
}
|
|
|
|
return hasChanges;
|
|
}
|
|
}
|
|
}
|