浏览代码

rework movie suggestion queryies

Luke Pulverenti 9 年之前
父节点
当前提交
05fedd2b61
共有 2 个文件被更改,包括 73 次插入64 次删除
  1. 71 64
      MediaBrowser.Api/Movies/MoviesService.cs
  2. 2 0
      MediaBrowser.Controller/Entities/InternalItemsQuery.cs

+ 71 - 64
MediaBrowser.Api/Movies/MoviesService.cs

@@ -139,28 +139,19 @@ namespace MediaBrowser.Api.Movies
                     typeof(Trailer).Name,
                     //typeof(LiveTvProgram).Name
                 },
-               // IsMovie = true
+                // IsMovie = true
             };
 
             var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
             var movies = _libraryManager.GetItemList(query, parentIds)
                 .OrderBy(i => (int)i.SourceType);
 
-            var listEligibleForCategories = new List<BaseItem>();
             var listEligibleForSuggestion = new List<BaseItem>();
 
             var list = movies.ToList();
 
-            listEligibleForCategories.AddRange(list);
             listEligibleForSuggestion.AddRange(list);
 
-            listEligibleForCategories = listEligibleForCategories
-                // Exclude trailers from the suggestion categories
-                .Where(i => i is Movie)
-                .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
-                .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
-                .ToList();
-
             listEligibleForSuggestion = listEligibleForSuggestion
                 .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
                 .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
@@ -170,7 +161,7 @@ namespace MediaBrowser.Api.Movies
 
             dtoOptions.Fields = request.GetItemFields().ToList();
 
-            var result = GetRecommendationCategories(user, listEligibleForCategories, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, dtoOptions);
+            var result = GetRecommendationCategories(user, request.ParentId, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, dtoOptions);
 
             return ToOptimizedResult(result);
         }
@@ -233,44 +224,43 @@ namespace MediaBrowser.Api.Movies
             return result;
         }
 
-        private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, List<BaseItem> allMoviesForCategories, List<BaseItem> allMovies, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
+        private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, string parentId, List<BaseItem> allMovies, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
         {
             var categories = new List<RecommendationDto>();
 
-            var recentlyPlayedMovies = allMoviesForCategories
-                .Select(i =>
+            var parentIds = string.IsNullOrWhiteSpace(parentId) ? new string[] { } : new[] { parentId };
+            var query = new InternalItemsQuery(user)
+            {
+                IncludeItemTypes = new[]
                 {
-                    var userdata = _userDataRepository.GetUserData(user, i);
-                    return new Tuple<BaseItem, bool, DateTime>(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue);
-                })
-                .Where(i => i.Item2)
-                .OrderByDescending(i => i.Item3)
-                .Select(i => i.Item1)
-                .ToList();
+                    typeof(Movie).Name,
+                    //typeof(Trailer).Name,
+                    //typeof(LiveTvProgram).Name
+                },
+                // IsMovie = true
+                SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random },
+                SortOrder = SortOrder.Descending,
+                Limit = 7
+            };
 
-            var excludeFromLiked = recentlyPlayedMovies.Take(10);
-            var likedMovies = allMovies
-                .Select(i =>
-                {
-                    var score = 0;
-                    var userData = _userDataRepository.GetUserData(user, i);
+            var recentlyPlayedMovies = _libraryManager.GetItemList(query, parentIds).ToList();
 
-                    if (userData.IsFavorite)
-                    {
-                        score = 2;
-                    }
-                    else
-                    {
-                        score = userData.Likes.HasValue ? userData.Likes.Value ? 1 : -1 : 0;
-                    }
+            var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
+            {
+                IncludeItemTypes = new[]
+                {
+                   typeof(Movie).Name,
+                   typeof(Trailer).Name,
+                   typeof(LiveTvProgram).Name
+                },
+                IsMovie = true,
+                SortBy = new[] { ItemSortBy.Random },
+                SortOrder = SortOrder.Descending,
+                Limit = 10,
+                IsFavoriteOrLiked = true,
+                ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id.ToString("N")).ToArray()
 
-                    return new Tuple<BaseItem, int>(i, score);
-                })
-                .OrderByDescending(i => i.Item2)
-                .ThenBy(i => Guid.NewGuid())
-                .Where(i => i.Item2 > 0)
-                .Select(i => i.Item1)
-                .Where(i => !excludeFromLiked.Contains(i));
+            }, parentIds);
 
             var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
             // Get recently played directors
@@ -286,8 +276,8 @@ namespace MediaBrowser.Api.Movies
             var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(7).OrderBy(i => Guid.NewGuid()), itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
             var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
 
-            var hasDirectorFromRecentlyPlayed = GetWithDirector(user, allMovies, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
-            var hasActorFromRecentlyPlayed = GetWithActor(user, allMovies, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
+            var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
+            var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
 
             var categoryTypes = new List<IEnumerator<RecommendationDto>>
             {
@@ -330,23 +320,34 @@ namespace MediaBrowser.Api.Movies
             return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid());
         }
 
-        private IEnumerable<RecommendationDto> GetWithDirector(User user, List<BaseItem> allMovies, IEnumerable<string> directors, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
+        private IEnumerable<RecommendationDto> GetWithDirector(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
         {
-            var userId = user.Id;
-
-            foreach (var director in directors)
+            foreach (var name in names)
             {
-                var items = allMovies
-                    .Where(i => _libraryManager.GetPeople(i).Any(p => string.Equals(p.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) && string.Equals(p.Name, director, StringComparison.OrdinalIgnoreCase)))
-                    .Take(itemLimit)
-                    .ToList();
+                var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
+                {
+                    Person = name,
+                    // Account for duplicates by imdb id, since the database doesn't support this yet
+                    Limit = itemLimit + 2,
+                    PersonTypes = new[] { PersonType.Director },
+                    IncludeItemTypes = new[]
+                    {
+                        typeof(Movie).Name,
+                        typeof(Trailer).Name,
+                        typeof(LiveTvProgram).Name
+                    },
+                    IsMovie = true
+
+                }).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
+                .Take(itemLimit)
+                .ToList();
 
                 if (items.Count > 0)
                 {
                     yield return new RecommendationDto
                     {
-                        BaselineItemName = director,
-                        CategoryId = director.GetMD5().ToString("N"),
+                        BaselineItemName = name,
+                        CategoryId = name.GetMD5().ToString("N"),
                         RecommendationType = type,
                         Items = _dtoService.GetBaseItemDtos(items, dtoOptions, user).ToArray()
                     };
@@ -354,20 +355,26 @@ namespace MediaBrowser.Api.Movies
             }
         }
 
-        private IEnumerable<RecommendationDto> GetWithActor(User user, List<BaseItem> allMovies, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
+        private IEnumerable<RecommendationDto> GetWithActor(User user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
         {
             foreach (var name in names)
             {
-                var itemsWithActor = _libraryManager.GetItemIds(new InternalItemsQuery(user)
+                var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
                 {
-                    Person = name
-
-                });
-
-                var items = allMovies
-                    .Where(i => itemsWithActor.Contains(i.Id))
-                    .Take(itemLimit)
-                    .ToList();
+                    Person = name,
+                    // Account for duplicates by imdb id, since the database doesn't support this yet
+                    Limit = itemLimit + 2,
+                    IncludeItemTypes = new[]
+                    {
+                        typeof(Movie).Name,
+                        typeof(Trailer).Name,
+                        typeof(LiveTvProgram).Name
+                    },
+                    IsMovie = true
+
+                }).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
+                .Take(itemLimit)
+                .ToList();
 
                 if (items.Count > 0)
                 {

+ 2 - 0
MediaBrowser.Controller/Entities/InternalItemsQuery.cs

@@ -53,6 +53,7 @@ namespace MediaBrowser.Controller.Entities
         public string Person { get; set; }
         public string[] PersonIds { get; set; }
         public string[] ItemIds { get; set; }
+        public string[] ExcludeItemIds { get; set; }
         public string AdjacentTo { get; set; }
         public string[] PersonTypes { get; set; }
 
@@ -166,6 +167,7 @@ namespace MediaBrowser.Controller.Entities
             PersonIds = new string[] { };
             ChannelIds = new string[] { };
             ItemIds = new string[] { };
+            ExcludeItemIds = new string[] { };
             AncestorIds = new string[] { };
             TopParentIds = new string[] { };
             ExcludeTags = new string[] { };