From 54177fbd60e6a3bb84bfd54d76f76a409f990d9b Mon Sep 17 00:00:00 2001 From: softworkz Date: Tue, 6 Oct 2015 00:03:58 +0200 Subject: [PATCH] Remote-Search: Suppress duplicates when agregating results from multiple providers This is a revision to pull request #1205 which tries to avoid returning duplicate results from multiple providers. Duplicates are eliminated in two stages: * Check for duplicate provider ids * In case of movies and series: Also remove duplicates by title/year combination The second stage is required because search results of themoviedb and thetvdb do not contain external ids and performing separate queries for each individual result would be too expensive. This is not an ideal solution, but Name/Year is anyway just exactly that information which is presented to the client in the results - apart from the image, of course. Images are only aggregated on matching provider ids, though. To allow image aggregation over all search results, the breaking condition once the result list is full has been removed.. --- .../Manager/ProviderManager.cs | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 807b8bc227..fc2f27bdd6 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -700,7 +700,7 @@ namespace MediaBrowser.Providers.Manager // Manual edit occurred // Even if save local is off, save locally anyway if the metadata file already exists - if (fileSaver == null || !isEnabledFor || !_fileSystem.FileExists(fileSaver.GetSavePath(item))) + if (fileSaver == null || !isEnabledFor || !_fileSystem.FileExists(fileSaver.GetSavePath(item))) { return false; } @@ -759,6 +759,8 @@ namespace MediaBrowser.Providers.Manager } var resultList = new List(); + var foundProviderIds = new Dictionary, RemoteSearchResult>(); + var foundTitleYearStrings = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var provider in providers) { @@ -766,16 +768,50 @@ namespace MediaBrowser.Providers.Manager { var results = await GetSearchResults(provider, searchInfo.SearchInfo, cancellationToken).ConfigureAwait(false); - var list = results.ToList(); - - if (list.Count > 0) + foreach (var result in results) { - resultList.AddRange(list.Take(maxResults - resultList.Count)); - } + var bFound = false; - if (resultList.Count >= maxResults) - { - return resultList; + // This check prevents duplicate search results by comparing provider ids + foreach (var providerId in result.ProviderIds) + { + var idTuple = new Tuple(providerId.Key.ToLower(), providerId.Value.ToLower()); + + if (!foundProviderIds.ContainsKey(idTuple)) + { + foundProviderIds.Add(idTuple, result); + } + else + { + bFound = true; + var existingResult = foundProviderIds[idTuple]; + if (string.IsNullOrEmpty(existingResult.ImageUrl) && !string.IsNullOrEmpty(result.ImageUrl)) + { + existingResult.ImageUrl = result.ImageUrl; + } + } + } + + // This is a workaround duplicate check for movies, where intersecting provider ids are not always available + if (typeof(TItemType) == typeof(Movie) || typeof(TItemType) == typeof(Series)) + { + var titleYearString = string.Format("{0} ({1})", result.Name, result.ProductionYear); + + if (foundTitleYearStrings.Contains(titleYearString)) + { + bFound = true; + } + else + { + foundTitleYearStrings.Add(titleYearString); + } + + } + + if (!bFound && resultList.Count < maxResults) + { + resultList.Add(result); + } } } catch (Exception ex)