using System.Collections.Generic; using System.Linq; using NLog; using NzbDrone.Core.Datastore; using NzbDrone.Core.Languages; using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Movies.Translations; namespace NzbDrone.Core.Movies { public interface IMovieMetadataRepository : IBasicRepository { MovieMetadata FindByTmdbId(int tmdbId); MovieMetadata FindByImdbId(string imdbId); List FindById(List tmdbIds); List GetMoviesWithCollections(); List GetMoviesByCollectionTmdbId(int collectionId); bool UpsertMany(List data); } public class MovieMetadataRepository : BasicRepository, IMovieMetadataRepository { private readonly Logger _logger; public MovieMetadataRepository(IMainDatabase database, IEventAggregator eventAggregator, Logger logger) : base(database, eventAggregator) { _logger = logger; } public MovieMetadata FindByTmdbId(int tmdbId) { return Query(x => x.TmdbId == tmdbId).FirstOrDefault(); } public MovieMetadata FindByImdbId(string imdbId) { return Query(x => x.ImdbId == imdbId).FirstOrDefault(); } public List FindById(List tmdbIds) { return Query(x => Enumerable.Contains(tmdbIds, x.TmdbId)); } public List GetMoviesWithCollections() { var movieDictionary = new Dictionary(); var builder = new SqlBuilder(_database.DatabaseType) .LeftJoin((mm, t) => mm.Id == t.MovieMetadataId) .Where(x => x.CollectionTmdbId > 0); _ = _database.QueryJoined( builder, (metadata, translation) => { if (!movieDictionary.TryGetValue(metadata.Id, out var movieEntry)) { movieEntry = metadata; movieDictionary.Add(movieEntry.Id, movieEntry); } if (translation != null) { movieEntry.Translations.Add(translation); } else { // Add a translation to avoid filename builder making another call thinking translations are not loaded // Optimize this later by pulling translations with metadata always movieEntry.Translations.Add(new MovieTranslation { Title = movieEntry.Title, Language = Language.English }); } return movieEntry; }); return movieDictionary.Values.ToList(); } public List GetMoviesByCollectionTmdbId(int collectionId) { return Query(x => x.CollectionTmdbId == collectionId); } public bool UpsertMany(List data) { var existingMetadata = FindById(data.Select(x => x.TmdbId).ToList()); var updateMetadataList = new List(); var addMetadataList = new List(); var upToDateMetadataCount = 0; foreach (var meta in data) { var existing = existingMetadata.SingleOrDefault(x => x.TmdbId == meta.TmdbId); if (existing != null) { meta.UseDbFieldsFrom(existing); if (!meta.Equals(existing)) { updateMetadataList.Add(meta); } else { upToDateMetadataCount++; } } else { addMetadataList.Add(meta); } } UpdateMany(updateMetadataList); InsertMany(addMetadataList); _logger.Debug($"{upToDateMetadataCount} movie metadata up to date; Updating {updateMetadataList.Count}, Adding {addMetadataList.Count} movie metadata entries."); return updateMetadataList.Count > 0 || addMetadataList.Count > 0; } } }