Add batch method for people names

This commit is contained in:
Shadowghost
2026-05-24 18:26:21 +02:00
parent 1175846120
commit cb9d6e9884
4 changed files with 82 additions and 0 deletions

View File

@@ -3394,6 +3394,12 @@ namespace Emby.Server.Implementations.Library
return _peopleRepository.GetPeopleNames(query);
}
/// <inheritdoc/>
public IReadOnlyDictionary<Guid, IReadOnlyList<string>> GetPeopleNamesByItem(IReadOnlyList<Guid> itemIds, IReadOnlyList<string> personTypes)
{
return _peopleRepository.GetPeopleNamesByItem(itemIds, personTypes);
}
public void UpdatePeople(BaseItem item, List<PersonInfo> people)
{
UpdatePeopleAsync(item, people, CancellationToken.None).GetAwaiter().GetResult();

View File

@@ -165,6 +165,64 @@ public class PeopleRepository(IDbContextFactory<JellyfinDbContext> dbProvider, I
transaction.Commit();
}
/// <inheritdoc/>
public IReadOnlyDictionary<Guid, IReadOnlyList<string>> GetPeopleNamesByItem(IReadOnlyList<Guid> itemIds, IReadOnlyList<string> personTypes)
{
if (itemIds.Count == 0)
{
return new Dictionary<Guid, IReadOnlyList<string>>();
}
using var context = _dbProvider.CreateDbContext();
var query = context.PeopleBaseItemMap
.AsNoTracking()
.Where(m => itemIds.Contains(m.ItemId));
if (personTypes.Count > 0)
{
query = query.Where(m => personTypes.Contains(m.People.PersonType));
}
// One round-trip: pull (ItemId, ListOrder, Name) sorted by ItemId+ListOrder, group in memory.
var rows = query
.OrderBy(m => m.ItemId)
.ThenBy(m => m.ListOrder)
.Select(m => new { m.ItemId, m.People.Name })
.ToArray();
var result = new Dictionary<Guid, IReadOnlyList<string>>();
List<string>? current = null;
var currentId = Guid.Empty;
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var row in rows)
{
if (row.ItemId != currentId)
{
if (current is { Count: > 0 })
{
result[currentId] = current;
}
currentId = row.ItemId;
current = new List<string>();
seen.Clear();
}
if (!string.IsNullOrWhiteSpace(row.Name) && seen.Add(row.Name))
{
current!.Add(row.Name);
}
}
if (current is { Count: > 0 })
{
result[currentId] = current;
}
return result;
}
private PersonInfo Map(People people)
{
var mapping = people.BaseItems?.FirstOrDefault();

View File

@@ -597,6 +597,14 @@ namespace MediaBrowser.Controller.Library
/// <returns>List&lt;System.String&gt;.</returns>
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery query);
/// <summary>
/// Gets the people names per item for a batch of item IDs in a single DB round-trip.
/// </summary>
/// <param name="itemIds">The item IDs to look up.</param>
/// <param name="personTypes">Optional person types to include. Empty for all.</param>
/// <returns>Dictionary keyed by item id; values are the per-item people names. Items with no people are absent.</returns>
IReadOnlyDictionary<Guid, IReadOnlyList<string>> GetPeopleNamesByItem(IReadOnlyList<Guid> itemIds, IReadOnlyList<string> personTypes);
/// <summary>
/// Queries the items.
/// </summary>

View File

@@ -32,4 +32,14 @@ public interface IPeopleRepository
/// <param name="filter">The query.</param>
/// <returns>The list of people names matching the filter.</returns>
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery filter);
/// <summary>
/// Gets the people names per item for a batch of item IDs, preserving per-item list order.
/// One database round-trip for the whole batch; grouped by item id in memory.
/// Items with no people are omitted from the returned dictionary.
/// </summary>
/// <param name="itemIds">The item IDs to get people for.</param>
/// <param name="personTypes">Optional person types to include (e.g. "Actor", "Director"). Empty for all.</param>
/// <returns>Dictionary keyed by item id; values are the per-item people names.</returns>
IReadOnlyDictionary<Guid, IReadOnlyList<string>> GetPeopleNamesByItem(IReadOnlyList<Guid> itemIds, IReadOnlyList<string> personTypes);
}