Sfoglia il codice sorgente

update artist queries

Luke Pulverenti 9 anni fa
parent
commit
d1d0487fee

+ 2 - 1
MediaBrowser.Api/FilterService.cs

@@ -103,7 +103,8 @@ namespace MediaBrowser.Api
                 User = user,
                 MediaTypes = request.GetMediaTypes(),
                 IncludeItemTypes = request.GetIncludeItemTypes(),
-                Recursive = true
+                Recursive = true,
+                EnableTotalRecordCount = false
             };
 
             return query;

+ 4 - 1
MediaBrowser.Api/GamesService.cs

@@ -162,7 +162,10 @@ namespace MediaBrowser.Api
 
             var items = user == null ? 
                 system.GetRecursiveChildren(i => i is Game) :
-                system.GetRecursiveChildren(user, i => i is Game);
+                system.GetRecursiveChildren(user, new InternalItemsQuery(user)
+                {
+                    IncludeItemTypes = new[] { typeof(Game).Name }
+                });
 
             var games = items.Cast<Game>().ToList();
 

+ 8 - 1
MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs

@@ -121,6 +121,13 @@ namespace MediaBrowser.Api.UserLibrary
             var includeItemTypes = request.GetIncludeItemTypes();
             var mediaTypes = request.GetMediaTypes();
 
+            var query = new InternalItemsQuery(user)
+            {
+                ExcludeItemTypes = excludeItemTypes,
+                IncludeItemTypes = includeItemTypes,
+                MediaTypes = mediaTypes
+            };
+
             Func<BaseItem, bool> filter = i => FilterItem(request, i, excludeItemTypes, includeItemTypes, mediaTypes);
 
             if (parentItem.IsFolder)
@@ -130,7 +137,7 @@ namespace MediaBrowser.Api.UserLibrary
                 if (!string.IsNullOrWhiteSpace(request.UserId))
                 {
                     items = request.Recursive ?
-                        folder.GetRecursiveChildren(user, filter) :
+                        folder.GetRecursiveChildren(user, query) :
                         folder.GetChildren(user, true).Where(filter);
                 }
                 else

+ 3 - 9
MediaBrowser.Api/UserLibrary/ItemsService.cs

@@ -138,25 +138,19 @@ namespace MediaBrowser.Api.UserLibrary
 
             if (request.Recursive)
             {
-                var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
-
-                return result;
+                return await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
             }
 
             if (user == null)
             {
-                var result = await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
-
-                return result;
+                return await ((Folder)item).GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
             }
 
             var userRoot = item as UserRootFolder;
 
             if (userRoot == null)
             {
-                var result = await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
-
-                return result;
+                return await ((Folder)item).GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
             }
 
             IEnumerable<BaseItem> items = ((Folder)item).GetChildren(user, true);

+ 10 - 26
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

@@ -56,36 +56,20 @@ namespace MediaBrowser.Controller.Entities.Audio
 
         public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
         {
-            var itemByNameFilter = GetItemFilter();
+            if (query.IncludeItemTypes.Length == 0)
+            {
+                query.IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name };
+                query.ArtistNames = new[] { Name };
+            }
 
-            if (query.User != null)
+            // Need this for now since the artist filter isn't yet supported by the db
+            if (ConfigurationManager.Configuration.SchemaVersion < 79)
             {
-                return query.User.RootFolder
-                    .GetRecursiveChildren(query.User, i =>
-                    {
-                        if (query.IsFolder.HasValue)
-                        {
-                            if (query.IsFolder.Value != i.IsFolder)
-                            {
-                                return false;
-                            }
-                        }
-                        return itemByNameFilter(i);
-                    });
+                var filter = GetItemFilter();
+                return LibraryManager.GetItemList(query).Where(filter);
             }
 
-            return LibraryManager.RootFolder
-                .GetRecursiveChildren(i =>
-                {
-                    if (query.IsFolder.HasValue)
-                    {
-                        if (query.IsFolder.Value != i.IsFolder)
-                        {
-                            return false;
-                        }
-                    }
-                    return itemByNameFilter(i);
-                });
+            return LibraryManager.GetItemList(query);
         }
 
         protected override IEnumerable<BaseItem> ActualChildren

+ 39 - 32
MediaBrowser.Controller/Entities/Folder.cs

@@ -749,7 +749,7 @@ namespace MediaBrowser.Controller.Entities
         {
             var user = query.User;
 
-            if (RequiresPostFiltering(query))
+            if (!query.ForceDirect && RequiresPostFiltering(query))
             {
                 IEnumerable<BaseItem> items;
                 Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
@@ -760,7 +760,7 @@ namespace MediaBrowser.Controller.Entities
                 }
                 else
                 {
-                    items = GetRecursiveChildren(user, filter);
+                    items = GetRecursiveChildren(user, query);
                 }
 
                 return PostFilterAndSort(items, query);
@@ -817,19 +817,24 @@ namespace MediaBrowser.Controller.Entities
                         return true;
                     }
                 }
-                if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
-                {
-                    Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
-                    return true;
-                }
-                if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
+
+                if (ConfigurationManager.Configuration.SchemaVersion < 79)
                 {
-                    Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
-                    return true;
+                    if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
+                    {
+                        Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
+                        return true;
+                    }
+                    if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
+                    {
+                        Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
+                        return true;
+                    }
                 }
-                if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
+
+                if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
                 {
-                    Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
+                    Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
                     return true;
                 }
                 if (query.SortBy.Contains(ItemSortBy.Budget, StringComparer.OrdinalIgnoreCase))
@@ -1109,10 +1114,13 @@ namespace MediaBrowser.Controller.Entities
                 return true;
             }
 
-            if (query.ArtistNames.Length > 0)
+            if (ConfigurationManager.Configuration.SchemaVersion < 79)
             {
-                Logger.Debug("Query requires post-filtering due to ArtistNames");
-                return true;
+                if (query.ArtistNames.Length > 0)
+                {
+                    Logger.Debug("Query requires post-filtering due to ArtistNames");
+                    return true;
+                }
             }
 
             return false;
@@ -1178,7 +1186,7 @@ namespace MediaBrowser.Controller.Entities
             else
             {
                 items = query.Recursive
-                   ? GetRecursiveChildren(user, filter)
+                   ? GetRecursiveChildren(user, query)
                    : GetChildren(user, true).Where(filter);
             }
 
@@ -1215,19 +1223,14 @@ namespace MediaBrowser.Controller.Entities
         /// <summary>
         /// Adds the children to list.
         /// </summary>
-        /// <param name="user">The user.</param>
-        /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
-        /// <param name="result">The result.</param>
-        /// <param name="recursive">if set to <c>true</c> [recursive].</param>
-        /// <param name="filter">The filter.</param>
         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, Func<BaseItem, bool> filter)
+        private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query)
         {
             foreach (var child in GetEligibleChildrenForRecursiveChildren(user))
             {
                 if (child.IsVisible(user))
                 {
-                    if (filter == null || filter(child))
+                    if (query == null || UserViewBuilder.FilterItem(child, query))
                     {
                         result[child.Id] = child;
                     }
@@ -1236,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities
                     {
                         var folder = (Folder)child;
 
-                        folder.AddChildren(user, includeLinkedChildren, result, true, filter);
+                        folder.AddChildren(user, includeLinkedChildren, result, true, query);
                     }
                 }
             }
@@ -1247,7 +1250,7 @@ namespace MediaBrowser.Controller.Entities
                 {
                     if (child.IsVisible(user))
                     {
-                        if (filter == null || filter(child))
+                        if (query == null || UserViewBuilder.FilterItem(child, query))
                         {
                             result[child.Id] = child;
                         }
@@ -1265,10 +1268,10 @@ namespace MediaBrowser.Controller.Entities
         /// <exception cref="System.ArgumentNullException"></exception>
         public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
         {
-            return GetRecursiveChildren(user, i => true);
+            return GetRecursiveChildren(user, null);
         }
 
-        public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
+        public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
         {
             if (user == null)
             {
@@ -1277,7 +1280,7 @@ namespace MediaBrowser.Controller.Entities
 
             var result = new Dictionary<Guid, BaseItem>();
 
-            AddChildren(user, true, result, true, filter);
+            AddChildren(user, true, result, true, query);
 
             return result.Values;
         }
@@ -1534,7 +1537,8 @@ namespace MediaBrowser.Controller.Entities
                 User = user,
                 Recursive = true,
                 IsFolder = false,
-                IsUnaired = false
+                IsUnaired = false,
+                EnableTotalRecordCount = false
 
             };
 
@@ -1562,7 +1566,8 @@ namespace MediaBrowser.Controller.Entities
             {
                 User = user,
                 Recursive = true,
-                IsFolder = false
+                IsFolder = false,
+                EnableTotalRecordCount = false
 
             }).ConfigureAwait(false);
 
@@ -1578,7 +1583,8 @@ namespace MediaBrowser.Controller.Entities
             {
                 Recursive = true,
                 IsFolder = false,
-                ExcludeLocationTypes = new[] { LocationType.Virtual }
+                ExcludeLocationTypes = new[] { LocationType.Virtual },
+                EnableTotalRecordCount = false
 
             }).Result;
 
@@ -1630,7 +1636,8 @@ namespace MediaBrowser.Controller.Entities
             {
                 Recursive = true,
                 IsFolder = false,
-                ExcludeLocationTypes = new[] { LocationType.Virtual }
+                ExcludeLocationTypes = new[] { LocationType.Virtual },
+                EnableTotalRecordCount = false
 
             }).Result;
 

+ 0 - 6
MediaBrowser.Controller/Entities/IItemByName.cs

@@ -15,12 +15,6 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>IEnumerable{BaseItem}.</returns>
         IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems);
 
-        /// <summary>
-        /// Gets the item filter.
-        /// </summary>
-        /// <returns>Func&lt;BaseItem, System.Boolean&gt;.</returns>
-        Func<BaseItem, bool> GetItemFilter();
-
         IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query);
     }
 

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

@@ -19,8 +19,6 @@ namespace MediaBrowser.Controller.Entities
 
         public User User { get; set; }
 
-        public Func<BaseItem, bool> Filter { get; set; }
-
         public bool? IsFolder { get; set; }
         public bool? IsFavorite { get; set; }
         public bool? IsFavoriteOrLiked { get; set; }
@@ -138,6 +136,7 @@ namespace MediaBrowser.Controller.Entities
 
         public bool GroupByPresentationUniqueKey { get; set; }
         public bool EnableTotalRecordCount { get; set; }
+        public bool ForceDirect { get; set; }
 
         public InternalItemsQuery()
         {

+ 8 - 4
MediaBrowser.Controller/Entities/TV/Series.cs

@@ -381,14 +381,18 @@ namespace MediaBrowser.Controller.Entities.TV
                 }
                 else
                 {
-                    episodes = GetRecursiveChildren(user, i => i is Episode)
-                        .Cast<Episode>();
+                    episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
+                    {
+                        IncludeItemTypes = new[] { typeof(Episode).Name }
+                    }).Cast<Episode>();
                 }
             }
             else
             {
-                episodes = GetRecursiveChildren(user, i => i is Episode)
-                    .Cast<Episode>();
+                episodes = GetRecursiveChildren(user, new InternalItemsQuery(user)
+                {
+                    IncludeItemTypes = new[] { typeof(Episode).Name }
+                }).Cast<Episode>();
             }
 
             episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons);

+ 7 - 4
MediaBrowser.Controller/Entities/UserView.cs

@@ -66,7 +66,8 @@ namespace MediaBrowser.Controller.Entities
         {
             var result = GetItems(new InternalItemsQuery
             {
-                User = user
+                User = user,
+                EnableTotalRecordCount = false
 
             }).Result;
 
@@ -83,17 +84,19 @@ namespace MediaBrowser.Controller.Entities
             return true;
         }
 
-        public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
+        public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
         {
             var result = GetItems(new InternalItemsQuery
             {
                 User = user,
                 Recursive = true,
-                Filter = filter
+                EnableTotalRecordCount = false,
+
+                ForceDirect = true
 
             }).Result;
 
-            return result.Items;
+            return result.Items.Where(i => UserViewBuilder.FilterItem(i, query));
         }
 
         protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)

+ 28 - 17
MediaBrowser.Controller/Entities/UserViewBuilder.cs

@@ -128,7 +128,11 @@ namespace MediaBrowser.Controller.Entities
                     {
                         if (query.Recursive)
                         {
-                            return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query);
+                            query.Recursive = true;
+                            query.ParentId = queryParent.Id;
+                            query.SetUser(user);
+
+                            return _libraryManager.GetItemsResult(query);
                         }
                         return GetResult(queryParent.GetChildren(user, true), queryParent, query);
                     }
@@ -328,9 +332,13 @@ namespace MediaBrowser.Controller.Entities
 
         private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
         {
-            var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
-                .Where(i => !i.IsFolder)
-                .OfType<IHasAlbumArtist>();
+            var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
+            {
+                Recursive = true,
+                ParentId = parent.Id,
+                IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
+
+            }).Cast<IHasAlbumArtist>();
 
             var artists = _libraryManager.GetAlbumArtists(items);
 
@@ -339,9 +347,13 @@ namespace MediaBrowser.Controller.Entities
 
         private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
         {
-            var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
-                .Where(i => !i.IsFolder)
-                .OfType<IHasArtist>();
+            var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
+            {
+                Recursive = true,
+                ParentId = parent.Id,
+                IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name }
+
+            }).Cast<IHasArtist>();
 
             var artists = _libraryManager.GetArtists(items);
 
@@ -350,9 +362,13 @@ namespace MediaBrowser.Controller.Entities
 
         private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
         {
-            var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
-                .Where(i => !i.IsFolder)
-                .OfType<IHasAlbumArtist>();
+            var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
+            {
+                Recursive = true,
+                ParentId = parent.Id,
+                IncludeItemTypes = new[] { typeof(Audio.Audio).Name }
+
+            }).Cast<IHasAlbumArtist>();
 
             var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
 
@@ -753,9 +769,9 @@ namespace MediaBrowser.Controller.Entities
             return PostFilterAndSort(items, queryParent, null, query, _libraryManager);
         }
 
-        public bool FilterItem(BaseItem item, InternalItemsQuery query)
+        public static bool FilterItem(BaseItem item, InternalItemsQuery query)
         {
-            return Filter(item, query.User, query, _userDataManager, _libraryManager);
+            return Filter(item, query.User, query, BaseItem.UserDataManager, BaseItem.LibraryManager);
         }
 
         private QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
@@ -1274,11 +1290,6 @@ namespace MediaBrowser.Controller.Entities
                 return false;
             }
 
-            if (query.Filter != null && !query.Filter(item))
-            {
-                return false;
-            }
-
             UserItemData userData = null;
 
             if (query.IsLiked.HasValue)

+ 8 - 4
MediaBrowser.Controller/Playlists/Playlist.cs

@@ -63,13 +63,13 @@ namespace MediaBrowser.Controller.Playlists
             return GetPlayableItems(user).Result;
         }
 
-        public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
+        public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
         {
             var items = GetPlayableItems(user).Result;
 
-            if (filter != null)
+            if (query != null)
             {
-                items = items.Where(filter);
+                items = items.Where(i => UserViewBuilder.FilterItem(i, query));
             }
 
             return items;
@@ -129,7 +129,11 @@ namespace MediaBrowser.Controller.Playlists
 
                 var items = user == null
                     ? LibraryManager.RootFolder.GetRecursiveChildren(filter)
-                    : user.RootFolder.GetRecursiveChildren(user, filter);
+                    : user.RootFolder.GetRecursiveChildren(user, new InternalItemsQuery(user)
+                    {
+                        IncludeItemTypes = new[] { typeof(Audio).Name },
+                        ArtistNames = new[] { musicArtist.Name }
+                    });
 
                 return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
             }

+ 6 - 27
MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs

@@ -401,10 +401,10 @@ namespace MediaBrowser.Dlna.ContentDirectory
                 SortOrder = sort.SortOrder,
                 User = user,
                 Recursive = true,
-                Filter = FilterUnsupportedContent,
+                IsMissing = false,
+                ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name },
                 IsFolder = isFolder,
                 MediaTypes = mediaTypes.ToArray()
-
             });
         }
 
@@ -461,8 +461,10 @@ namespace MediaBrowser.Dlna.ContentDirectory
                 SortBy = sortOrders.ToArray(),
                 SortOrder = sort.SortOrder,
                 User = user,
-                Filter = FilterUnsupportedContent,
-                PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music }
+                IsMissing = false,
+                PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music },
+                ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name },
+                IsPlaceHolder = false
 
             }).ConfigureAwait(false);
 
@@ -579,29 +581,6 @@ namespace MediaBrowser.Dlna.ContentDirectory
             });
         }
 
-        private bool FilterUnsupportedContent(BaseItem i)
-        {
-            // Unplayable
-            if (i.LocationType == LocationType.Virtual && !i.IsFolder)
-            {
-                return false;
-            }
-
-            // Unplayable
-            var supportsPlaceHolder = i as ISupportsPlaceHolders;
-            if (supportsPlaceHolder != null && supportsPlaceHolder.IsPlaceHolder)
-            {
-                return false;
-            }
-
-            if (i is Game || i is Book)
-            {
-                //return false;
-            }
-
-            return true;
-        }
-
         private ServerItem GetItemFromObjectId(string id, User user)
         {
             return DidlBuilder.IsIdRoot(id)

+ 6 - 2
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -1448,8 +1448,12 @@ namespace MediaBrowser.Server.Implementations.Library
                 // Handle grouping
                 if (user != null && !string.IsNullOrWhiteSpace(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType))
                 {
-                    var collectionFolders = user.RootFolder.GetChildren(user, true).OfType<CollectionFolder>().Where(i => string.IsNullOrWhiteSpace(i.CollectionType) || string.Equals(i.CollectionType, view.ViewType, StringComparison.OrdinalIgnoreCase));
-                    return collectionFolders.SelectMany(i => GetTopParentsForQuery(i, user));
+                    return user.RootFolder
+                        .GetChildren(user, true)
+                        .OfType<CollectionFolder>()
+                        .Where(i => string.IsNullOrWhiteSpace(i.CollectionType) || string.Equals(i.CollectionType, view.ViewType, StringComparison.OrdinalIgnoreCase))
+                        .Where(i => user.Configuration.GroupedFolders.Contains(i.Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
+                        .SelectMany(i => GetTopParentsForQuery(i, user));
                 }
                 return new BaseItem[] { };
             }

+ 16 - 4
MediaBrowser.Server.Implementations/Library/MusicManager.cs

@@ -30,7 +30,10 @@ namespace MediaBrowser.Server.Implementations.Library
         public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user)
         {
             var genres = user.RootFolder
-                .GetRecursiveChildren(user, i => i is Audio)
+                .GetRecursiveChildren(user, new InternalItemsQuery(user)
+                {
+                    IncludeItemTypes = new[] { typeof(Audio).Name }
+                })
                 .Cast<Audio>()
                 .Where(i => i.HasAnyArtist(artist.Name))
                 .SelectMany(i => i.Genres)
@@ -43,7 +46,10 @@ namespace MediaBrowser.Server.Implementations.Library
         public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
         {
             var genres = item
-                .GetRecursiveChildren(user, i => i is Audio)
+                .GetRecursiveChildren(user, new InternalItemsQuery(user)
+                {
+                    IncludeItemTypes = new[] { typeof(Audio).Name }
+                })
                .Cast<Audio>()
                .SelectMany(i => i.Genres)
                .Concat(item.Genres)
@@ -55,7 +61,10 @@ namespace MediaBrowser.Server.Implementations.Library
         public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user)
         {
             var genres = item
-               .GetRecursiveChildren(user, i => i is Audio)
+               .GetRecursiveChildren(user, new InternalItemsQuery(user)
+               {
+                   IncludeItemTypes = new[] {typeof(Audio).Name}
+               })
                .Cast<Audio>()
                .SelectMany(i => i.Genres)
                .Concat(item.Genres)
@@ -67,7 +76,10 @@ namespace MediaBrowser.Server.Implementations.Library
         public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
         {
             var genres = item
-               .GetRecursiveChildren(user, i => i is Audio)
+               .GetRecursiveChildren(user, new InternalItemsQuery(user)
+               {
+                   IncludeItemTypes = new[] { typeof(Audio).Name }
+               })
                .Cast<Audio>()
                .SelectMany(i => i.Genres)
                .Concat(item.Genres)

+ 1 - 3
MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -1410,7 +1410,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 .Where(i => i.IsVisibleStandalone(user))
                 .ToList();
 
-            var items = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
+            return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
             {
                 MediaTypes = new[] { MediaType.Video },
                 Recursive = true,
@@ -1418,8 +1418,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 ExcludeLocationTypes = new[] { LocationType.Virtual },
                 Limit = Math.Min(10, query.Limit ?? int.MaxValue)
             });
-
-            return items;
         }
 
         public async Task<QueryResult<BaseItem>> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken)

+ 98 - 3
MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs

@@ -81,10 +81,13 @@ namespace MediaBrowser.Server.Implementations.Persistence
         private IDbCommand _deleteUserDataKeysCommand;
         private IDbCommand _saveUserDataKeysCommand;
 
+        private IDbCommand _deleteItemValuesCommand;
+        private IDbCommand _saveItemValuesCommand;
+
         private IDbCommand _updateInheritedRatingCommand;
         private IDbCommand _updateInheritedTagsCommand;
 
-        public const int LatestSchemaVersion = 78;
+        public const int LatestSchemaVersion = 79;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
@@ -136,6 +139,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
                                 "create table if not exists UserDataKeys (ItemId GUID, UserDataKey TEXT, PRIMARY KEY (ItemId, UserDataKey))",
                                 "create index if not exists idx_UserDataKeys1 on UserDataKeys(ItemId)",
 
+                                "create table if not exists ItemValues (ItemId GUID, Type INT, Value TEXT)",
+                                "create index if not exists idx_ItemValues on ItemValues(ItemId)",
+
                                 "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)",
                                 "create index if not exists idxPeopleItemId on People(ItemId)",
                                 "create index if not exists idxPeopleName on People(Name)",
@@ -565,6 +571,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
             _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@UserDataKey");
             _saveUserDataKeysCommand.Parameters.Add(_saveUserDataKeysCommand, "@Priority");
 
+            // item values
+            _deleteItemValuesCommand = _connection.CreateCommand();
+            _deleteItemValuesCommand.CommandText = "delete from ItemValues where ItemId=@Id";
+            _deleteItemValuesCommand.Parameters.Add(_deleteItemValuesCommand, "@Id");
+
+            _saveItemValuesCommand = _connection.CreateCommand();
+            _saveItemValuesCommand.CommandText = "insert into ItemValues (ItemId, Type, Value) values (@ItemId, @Type, @Value)";
+            _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@ItemId");
+            _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Type");
+            _saveItemValuesCommand.Parameters.Add(_saveItemValuesCommand, "@Value");
+
         }
 
         /// <summary>
@@ -851,6 +868,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
                     }
 
                     UpdateUserDataKeys(item.Id, item.GetUserDataKeys().Distinct(StringComparer.OrdinalIgnoreCase).ToList(), transaction);
+                    UpdateItemValues(item.Id, GetItemValues(item), transaction);
                 }
 
                 transaction.Commit();
@@ -1661,7 +1679,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
         {
             var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds;
 
-            if (elapsed >= 500)
+            if (elapsed >= 400)
             {
                 Logger.Debug("{2} query time (slow): {0}ms. Query: {1}",
                     Convert.ToInt32(elapsed),
@@ -1795,7 +1813,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
             }).ToArray());
         }
 
-        private Tuple<string,bool> MapOrderByField(string name)
+        private Tuple<string, bool> MapOrderByField(string name)
         {
             if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase))
             {
@@ -1838,6 +1856,14 @@ namespace MediaBrowser.Server.Implementations.Persistence
             {
                 return new Tuple<string, bool>("DateLastMediaAdded", false);
             }
+            if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase))
+            {
+                return new Tuple<string, bool>("(select value from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false);
+            }
+            if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase))
+            {
+                return new Tuple<string, bool>("(select value from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false);
+            }
 
             return new Tuple<string, bool>(name, false);
         }
@@ -2433,6 +2459,20 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 }
             }
 
+            if (query.ArtistNames.Length > 0)
+            {
+                var clauses = new List<string>();
+                var index = 0;
+                foreach (var artist in query.ArtistNames)
+                {
+                    clauses.Add("@ArtistName" + index + " in (select value from itemvalues where ItemId=Guid and Type <= 1)");
+                    cmd.Parameters.Add(cmd, "@ArtistName" + index, DbType.String).Value = artist;
+                    index++;
+                }
+                var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")";
+                whereClauses.Add(clause);
+            }
+
             if (query.Genres.Length > 0)
             {
                 var clauses = new List<string>();
@@ -2970,6 +3010,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 _deleteUserDataKeysCommand.Transaction = transaction;
                 _deleteUserDataKeysCommand.ExecuteNonQuery();
 
+                // Delete item values
+                _deleteItemValuesCommand.GetParameter(0).Value = id;
+                _deleteItemValuesCommand.Transaction = transaction;
+                _deleteItemValuesCommand.ExecuteNonQuery();
+
                 // Delete the item
                 _deleteItemCommand.GetParameter(0).Value = id;
                 _deleteItemCommand.Transaction = transaction;
@@ -3162,6 +3207,56 @@ namespace MediaBrowser.Server.Implementations.Persistence
             }
         }
 
+        private List<Tuple<int, string>> GetItemValues(BaseItem item)
+        {
+            var list = new List<Tuple<int, string>>();
+
+            var hasArtist = item as IHasArtist;
+            if (hasArtist != null)
+            {
+                list.AddRange(hasArtist.Artists.Select(i => new Tuple<int, string>(0, i)));
+            }
+
+            var hasAlbumArtist = item as IHasAlbumArtist;
+            if (hasAlbumArtist != null)
+            {
+                list.AddRange(hasAlbumArtist.AlbumArtists.Select(i => new Tuple<int, string>(1, i)));
+            }
+
+            return list;
+        }
+
+        private void UpdateItemValues(Guid itemId, List<Tuple<int, string>> values, IDbTransaction transaction)
+        {
+            if (itemId == Guid.Empty)
+            {
+                throw new ArgumentNullException("itemId");
+            }
+
+            if (values == null)
+            {
+                throw new ArgumentNullException("keys");
+            }
+
+            CheckDisposed();
+
+            // First delete 
+            _deleteItemValuesCommand.GetParameter(0).Value = itemId;
+            _deleteItemValuesCommand.Transaction = transaction;
+
+            _deleteItemValuesCommand.ExecuteNonQuery();
+
+            foreach (var pair in values)
+            {
+                _saveItemValuesCommand.GetParameter(0).Value = itemId;
+                _saveItemValuesCommand.GetParameter(1).Value = pair.Item1;
+                _saveItemValuesCommand.GetParameter(2).Value = pair.Item2;
+                _saveItemValuesCommand.Transaction = transaction;
+
+                _saveItemValuesCommand.ExecuteNonQuery();
+            }
+        }
+
         private void UpdateUserDataKeys(Guid itemId, List<string> keys, IDbTransaction transaction)
         {
             if (itemId == Guid.Empty)