rework movie suggestion queryies

This commit is contained in:
Luke Pulverenti 2016-05-31 14:42:32 -04:00
parent 977f62336b
commit 05fedd2b61
2 changed files with 72 additions and 63 deletions

View file

@ -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 recentlyPlayedMovies = _libraryManager.GetItemList(query, parentIds).ToList();
var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[]
{
var score = 0;
var userData = _userDataRepository.GetUserData(user, i);
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()
if (userData.IsFavorite)
{
score = 2;
}
else
{
score = userData.Likes.HasValue ? userData.Likes.Value ? 1 : -1 : 0;
}
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
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
});
var items = allMovies
.Where(i => itemsWithActor.Contains(i.Id))
.Take(itemLimit)
.ToList();
}).DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
.Take(itemLimit)
.ToList();
if (items.Count > 0)
{

View file

@ -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[] { };