2018-03-14 20:41:36 +00:00
using System ;
2017-01-03 19:24:55 +00:00
using System.Collections.Generic ;
2022-10-09 05:02:34 +00:00
using System.IO ;
2019-12-22 22:08:53 +00:00
using System.Linq ;
2019-12-18 21:56:41 +00:00
using Dapper ;
2016-12-29 15:04:01 +00:00
using NzbDrone.Core.Datastore ;
2019-12-15 15:04:42 +00:00
using NzbDrone.Core.MediaFiles ;
2019-12-22 22:08:53 +00:00
using NzbDrone.Core.Messaging.Events ;
2019-12-18 02:17:47 +00:00
using NzbDrone.Core.Movies.AlternativeTitles ;
2020-07-22 03:04:20 +00:00
using NzbDrone.Core.Movies.Translations ;
2019-12-18 21:56:41 +00:00
using NzbDrone.Core.Profiles ;
2019-12-18 02:17:47 +00:00
using NzbDrone.Core.Qualities ;
2016-12-29 15:04:01 +00:00
2018-03-14 20:41:36 +00:00
namespace NzbDrone.Core.Movies
2016-12-29 15:04:01 +00:00
{
public interface IMovieRepository : IBasicRepository < Movie >
{
bool MoviePathExists ( string path ) ;
2019-12-18 21:56:41 +00:00
List < Movie > FindByTitles ( List < string > titles ) ;
2016-12-29 15:04:01 +00:00
Movie FindByImdbId ( string imdbid ) ;
2017-01-23 13:04:01 +00:00
Movie FindByTmdbId ( int tmdbid ) ;
2019-12-18 21:56:41 +00:00
List < Movie > FindByTmdbId ( List < int > tmdbids ) ;
2017-01-16 21:40:59 +00:00
List < Movie > MoviesBetweenDates ( DateTime start , DateTime end , bool includeUnmonitored ) ;
2017-01-18 18:53:17 +00:00
PagingSpec < Movie > MoviesWithoutFiles ( PagingSpec < Movie > pagingSpec ) ;
2017-01-03 19:24:55 +00:00
List < Movie > GetMoviesByFileId ( int fileId ) ;
2022-03-08 02:03:00 +00:00
List < Movie > GetMoviesByCollectionTmdbId ( int collectionId ) ;
2017-01-03 19:24:55 +00:00
void SetFileId ( int fileId , int movieId ) ;
2017-02-10 05:15:41 +00:00
PagingSpec < Movie > MoviesWhereCutoffUnmet ( PagingSpec < Movie > pagingSpec , List < QualitiesBelowCutoff > qualitiesBelowCutoff ) ;
2019-07-16 02:27:35 +00:00
Movie FindByPath ( string path ) ;
2020-12-05 03:13:13 +00:00
Dictionary < int , string > AllMoviePaths ( ) ;
2020-09-04 02:50:56 +00:00
List < int > AllMovieTmdbIds ( ) ;
2020-11-27 05:36:18 +00:00
Dictionary < int , List < int > > AllMovieTags ( ) ;
2020-09-04 02:50:56 +00:00
List < int > GetRecommendations ( ) ;
2022-10-09 05:02:34 +00:00
bool ExistsByMetadataId ( int metadataId ) ;
2016-12-29 15:04:01 +00:00
}
public class MovieRepository : BasicRepository < Movie > , IMovieRepository
{
2019-12-18 21:56:41 +00:00
private readonly IProfileRepository _profileRepository ;
2021-02-03 21:26:10 +00:00
private readonly IAlternativeTitleRepository _alternativeTitleRepository ;
2019-12-18 21:56:41 +00:00
public MovieRepository ( IMainDatabase database ,
IProfileRepository profileRepository ,
2021-02-03 21:26:10 +00:00
IAlternativeTitleRepository alternativeTitleRepository ,
2019-12-18 21:56:41 +00:00
IEventAggregator eventAggregator )
2019-12-18 02:17:47 +00:00
: base ( database , eventAggregator )
2019-12-15 15:04:42 +00:00
{
2019-12-18 21:56:41 +00:00
_profileRepository = profileRepository ;
2021-02-03 21:26:10 +00:00
_alternativeTitleRepository = alternativeTitleRepository ;
2019-12-18 21:56:41 +00:00
}
2022-03-28 20:45:52 +00:00
protected override SqlBuilder Builder ( ) = > new SqlBuilder ( _database . DatabaseType )
2019-12-18 21:56:41 +00:00
. Join < Movie , Profile > ( ( m , p ) = > m . ProfileId = = p . Id )
2022-03-20 15:55:47 +00:00
. Join < Movie , MovieMetadata > ( ( m , p ) = > m . MovieMetadataId = = p . Id )
. LeftJoin < Movie , MovieFile > ( ( m , f ) = > m . Id = = f . MovieId )
. LeftJoin < MovieMetadata , AlternativeTitle > ( ( mm , t ) = > mm . Id = = t . MovieMetadataId ) ;
2019-12-18 21:56:41 +00:00
2022-03-20 15:55:47 +00:00
private Movie Map ( Dictionary < int , Movie > dict , Movie movie , Profile profile , MovieFile movieFile , AlternativeTitle altTitle = null , MovieTranslation translation = null )
2019-12-18 21:56:41 +00:00
{
Movie movieEntry ;
if ( ! dict . TryGetValue ( movie . Id , out movieEntry ) )
{
movieEntry = movie ;
movieEntry . Profile = profile ;
movieEntry . MovieFile = movieFile ;
dict . Add ( movieEntry . Id , movieEntry ) ;
}
if ( altTitle ! = null )
{
2022-03-20 15:55:47 +00:00
movieEntry . MovieMetadata . Value . AlternativeTitles . Add ( altTitle ) ;
2019-12-18 21:56:41 +00:00
}
2020-07-22 03:04:20 +00:00
if ( translation ! = null )
{
2022-03-20 15:55:47 +00:00
movieEntry . MovieMetadata . Value . Translations . Add ( translation ) ;
2020-07-22 03:04:20 +00:00
}
2019-12-18 21:56:41 +00:00
return movieEntry ;
}
2020-05-14 19:56:26 +00:00
protected override List < Movie > Query ( SqlBuilder builder )
2019-12-18 21:56:41 +00:00
{
var movieDictionary = new Dictionary < int , Movie > ( ) ;
2022-03-20 15:55:47 +00:00
_ = _database . QueryJoined < Movie , Profile , MovieFile , AlternativeTitle > (
2020-05-14 19:56:26 +00:00
builder ,
2022-03-20 15:55:47 +00:00
( movie , profile , file , altTitle ) = > Map ( movieDictionary , movie , profile , file , altTitle ) ) ;
2019-12-18 21:56:41 +00:00
2020-05-14 19:56:26 +00:00
return movieDictionary . Values . ToList ( ) ;
2019-12-18 21:56:41 +00:00
}
public override IEnumerable < Movie > All ( )
{
2021-02-03 21:26:10 +00:00
// the skips the join on profile and alternative title and populates manually
// to avoid repeatedly deserializing the same profile / movie
2022-03-28 20:45:52 +00:00
var builder = new SqlBuilder ( _database . DatabaseType )
2022-03-20 15:55:47 +00:00
. LeftJoin < Movie , MovieFile > ( ( m , f ) = > m . MovieFileId = = f . Id )
. LeftJoin < Movie , MovieMetadata > ( ( m , f ) = > m . MovieMetadataId = = f . Id ) ;
2019-12-18 21:56:41 +00:00
var profiles = _profileRepository . All ( ) . ToDictionary ( x = > x . Id ) ;
2021-02-03 21:26:10 +00:00
var titles = _alternativeTitleRepository . All ( )
2022-03-20 15:55:47 +00:00
. GroupBy ( x = > x . MovieMetadataId )
2021-02-03 21:26:10 +00:00
. ToDictionary ( x = > x . Key , y = > y . ToList ( ) ) ;
2019-12-18 21:56:41 +00:00
2022-03-20 15:55:47 +00:00
return _database . QueryJoined < Movie , MovieFile , MovieMetadata > (
2020-05-14 19:56:26 +00:00
builder ,
2022-03-20 15:55:47 +00:00
( movie , file , metadata ) = >
2021-02-03 21:26:10 +00:00
{
movie . MovieFile = file ;
2022-03-20 15:55:47 +00:00
movie . MovieMetadata = metadata ;
2021-02-03 21:26:10 +00:00
movie . Profile = profiles [ movie . ProfileId ] ;
2022-03-20 15:55:47 +00:00
if ( titles . TryGetValue ( movie . MovieMetadataId , out var altTitles ) )
2021-02-03 21:26:10 +00:00
{
2022-03-20 15:55:47 +00:00
movie . MovieMetadata . Value . AlternativeTitles = altTitles ;
2021-02-03 21:26:10 +00:00
}
return movie ;
} ) ;
2016-12-29 15:04:01 +00:00
}
public bool MoviePathExists ( string path )
{
2019-12-18 21:56:41 +00:00
return Query ( x = > x . Path = = path ) . Any ( ) ;
2016-12-29 15:04:01 +00:00
}
2019-12-18 21:56:41 +00:00
public List < Movie > FindByTitles ( List < string > titles )
2016-12-29 15:04:01 +00:00
{
2020-05-14 20:37:35 +00:00
var distinct = titles . Distinct ( ) . ToList ( ) ;
2020-10-07 20:45:04 +00:00
var results = new List < Movie > ( ) ;
results . AddRange ( FindByMovieTitles ( distinct ) ) ;
results . AddRange ( FindByAltTitles ( distinct ) ) ;
results . AddRange ( FindByTransTitles ( distinct ) ) ;
return results . DistinctBy ( x = > x . Id ) . ToList ( ) ;
}
// This is a bit of a hack, but if you try to combine / rationalise these then
// SQLite makes a mess of the query plan and ends up doing a table scan
private List < Movie > FindByMovieTitles ( List < string > titles )
{
2020-07-22 03:04:20 +00:00
var movieDictionary = new Dictionary < int , Movie > ( ) ;
2016-12-29 15:04:01 +00:00
2022-03-20 15:55:47 +00:00
var builder = new SqlBuilder ( _database . DatabaseType )
2022-03-28 20:45:52 +00:00
. Join < Movie , Profile > ( ( m , p ) = > m . ProfileId = = p . Id )
2022-03-20 15:55:47 +00:00
. Join < Movie , MovieMetadata > ( ( m , p ) = > m . MovieMetadataId = = p . Id )
2020-10-07 20:45:04 +00:00
. LeftJoin < Movie , MovieFile > ( ( m , f ) = > m . Id = = f . MovieId )
2022-03-20 15:55:47 +00:00
. Where < MovieMetadata > ( x = > titles . Contains ( x . CleanTitle ) | | titles . Contains ( x . CleanOriginalTitle ) ) ;
2020-07-22 03:04:20 +00:00
2022-03-20 15:55:47 +00:00
_ = _database . QueryJoined < Movie , Profile , MovieFile > (
2020-07-22 03:04:20 +00:00
builder ,
2022-03-20 15:55:47 +00:00
( movie , profile , file ) = > Map ( movieDictionary , movie , profile , file ) ) ;
2020-07-22 03:04:20 +00:00
return movieDictionary . Values . ToList ( ) ;
2016-12-29 15:04:01 +00:00
}
2020-10-07 20:45:04 +00:00
private List < Movie > FindByAltTitles ( List < string > titles )
{
var movieDictionary = new Dictionary < int , Movie > ( ) ;
2022-03-20 15:55:47 +00:00
var builder = new SqlBuilder ( _database . DatabaseType )
. Join < AlternativeTitle , MovieMetadata > ( ( t , mm ) = > t . MovieMetadataId = = mm . Id )
. Join < MovieMetadata , Movie > ( ( mm , m ) = > mm . Id = = m . MovieMetadataId )
. Join < Movie , Profile > ( ( m , p ) = > m . ProfileId = = p . Id )
. LeftJoin < Movie , MovieFile > ( ( m , f ) = > m . Id = = f . MovieId )
. Where < AlternativeTitle > ( x = > titles . Contains ( x . CleanTitle ) ) ;
2020-10-07 20:45:04 +00:00
2022-03-20 15:55:47 +00:00
_ = _database . QueryJoined < AlternativeTitle , Profile , Movie , MovieFile > (
2020-10-07 20:45:04 +00:00
builder ,
2022-03-20 15:55:47 +00:00
( altTitle , profile , movie , file ) = >
2020-10-07 20:45:04 +00:00
{
2022-03-20 15:55:47 +00:00
_ = Map ( movieDictionary , movie , profile , file , altTitle ) ;
2020-10-07 20:45:04 +00:00
return null ;
} ) ;
return movieDictionary . Values . ToList ( ) ;
}
private List < Movie > FindByTransTitles ( List < string > titles )
{
var movieDictionary = new Dictionary < int , Movie > ( ) ;
2022-03-20 15:55:47 +00:00
var builder = new SqlBuilder ( _database . DatabaseType )
. Join < MovieTranslation , MovieMetadata > ( ( t , mm ) = > t . MovieMetadataId = = mm . Id )
. Join < MovieMetadata , Movie > ( ( mm , m ) = > mm . Id = = m . MovieMetadataId )
2020-10-07 20:45:04 +00:00
. Join < Movie , Profile > ( ( m , p ) = > m . ProfileId = = p . Id )
2022-03-20 15:55:47 +00:00
. LeftJoin < Movie , MovieFile > ( ( m , f ) = > m . Id = = f . MovieId )
2020-10-07 20:45:04 +00:00
. Where < MovieTranslation > ( x = > titles . Contains ( x . CleanTitle ) ) ;
2022-03-20 15:55:47 +00:00
_ = _database . QueryJoined < MovieTranslation , Profile , Movie , MovieFile > (
2020-10-07 20:45:04 +00:00
builder ,
2022-03-20 15:55:47 +00:00
( trans , profile , movie , file ) = >
2020-10-07 20:45:04 +00:00
{
2022-03-20 15:55:47 +00:00
_ = Map ( movieDictionary , movie , profile , file , null , trans ) ;
2020-10-07 20:45:04 +00:00
return null ;
} ) ;
return movieDictionary . Values . ToList ( ) ;
}
2016-12-29 15:04:01 +00:00
public Movie FindByImdbId ( string imdbid )
{
2017-03-07 23:29:02 +00:00
var imdbIdWithPrefix = Parser . Parser . NormalizeImdbId ( imdbid ) ;
2022-03-20 15:55:47 +00:00
return imdbIdWithPrefix = = null ? null : Query ( x = > x . MovieMetadata . Value . ImdbId = = imdbIdWithPrefix ) . FirstOrDefault ( ) ;
2019-12-18 21:56:41 +00:00
}
public Movie FindByTmdbId ( int tmdbid )
{
2022-03-20 15:55:47 +00:00
return Query ( x = > x . MovieMetadata . Value . TmdbId = = tmdbid ) . FirstOrDefault ( ) ;
2019-12-18 21:56:41 +00:00
}
public List < Movie > FindByTmdbId ( List < int > tmdbids )
{
return Query ( x = > tmdbids . Contains ( x . TmdbId ) ) ;
2016-12-29 15:04:01 +00:00
}
2017-01-03 19:24:55 +00:00
public List < Movie > GetMoviesByFileId ( int fileId )
{
2019-12-18 21:56:41 +00:00
return Query ( x = > x . MovieFileId = = fileId ) ;
2017-01-03 19:24:55 +00:00
}
2022-03-08 02:03:00 +00:00
public List < Movie > GetMoviesByCollectionTmdbId ( int collectionId )
{
return Query ( x = > x . MovieMetadata . Value . CollectionTmdbId = = collectionId ) ;
}
2018-03-14 20:41:36 +00:00
public void SetFileId ( int fileId , int movieId )
2017-01-03 19:24:55 +00:00
{
2018-03-14 20:41:36 +00:00
SetFields ( new Movie { Id = movieId , MovieFileId = fileId } , movie = > movie . MovieFileId ) ;
2017-01-03 19:24:55 +00:00
}
2017-01-16 21:40:59 +00:00
public List < Movie > MoviesBetweenDates ( DateTime start , DateTime end , bool includeUnmonitored )
{
2019-12-18 21:56:41 +00:00
var builder = Builder ( )
. Where < Movie > ( m = >
2022-03-20 15:55:47 +00:00
( m . MovieMetadata . Value . InCinemas > = start & & m . MovieMetadata . Value . InCinemas < = end ) | |
( m . MovieMetadata . Value . PhysicalRelease > = start & & m . MovieMetadata . Value . PhysicalRelease < = end ) | |
( m . MovieMetadata . Value . DigitalRelease > = start & & m . MovieMetadata . Value . DigitalRelease < = end ) ) ;
2019-12-22 21:24:11 +00:00
2019-12-22 22:08:53 +00:00
if ( ! includeUnmonitored )
{
2019-12-18 21:56:41 +00:00
builder . Where < Movie > ( x = > x . Monitored = = true ) ;
2019-12-22 22:08:53 +00:00
}
2017-01-16 21:40:59 +00:00
2019-12-18 21:56:41 +00:00
return Query ( builder ) ;
2017-01-16 21:40:59 +00:00
}
2017-01-18 18:53:17 +00:00
2020-05-14 19:56:26 +00:00
public SqlBuilder MoviesWithoutFilesBuilder ( ) = > Builder ( )
. Where < Movie > ( x = > x . MovieFileId = = 0 ) ;
2019-12-18 21:56:41 +00:00
2017-01-18 18:53:17 +00:00
public PagingSpec < Movie > MoviesWithoutFiles ( PagingSpec < Movie > pagingSpec )
{
2020-05-14 19:56:26 +00:00
pagingSpec . Records = GetPagedRecords ( MoviesWithoutFilesBuilder ( ) , pagingSpec , PagedQuery ) ;
2019-12-18 21:56:41 +00:00
pagingSpec . TotalRecords = GetPagedRecordCount ( MoviesWithoutFilesBuilder ( ) . SelectCount ( ) , pagingSpec ) ;
2017-01-19 18:08:15 +00:00
return pagingSpec ;
}
2020-05-14 19:56:26 +00:00
public SqlBuilder MoviesWhereCutoffUnmetBuilder ( List < QualitiesBelowCutoff > qualitiesBelowCutoff ) = > Builder ( )
2019-12-18 21:56:41 +00:00
. Where < Movie > ( x = > x . MovieFileId ! = 0 )
. Where ( BuildQualityCutoffWhereClause ( qualitiesBelowCutoff ) ) ;
2017-01-23 13:04:01 +00:00
2017-02-10 05:15:41 +00:00
public PagingSpec < Movie > MoviesWhereCutoffUnmet ( PagingSpec < Movie > pagingSpec , List < QualitiesBelowCutoff > qualitiesBelowCutoff )
{
2020-05-14 19:56:26 +00:00
pagingSpec . Records = GetPagedRecords ( MoviesWhereCutoffUnmetBuilder ( qualitiesBelowCutoff ) , pagingSpec , PagedQuery ) ;
2019-12-18 21:56:41 +00:00
pagingSpec . TotalRecords = GetPagedRecordCount ( MoviesWhereCutoffUnmetBuilder ( qualitiesBelowCutoff ) . SelectCount ( ) , pagingSpec ) ;
2017-02-10 05:15:41 +00:00
return pagingSpec ;
}
private string BuildQualityCutoffWhereClause ( List < QualitiesBelowCutoff > qualitiesBelowCutoff )
{
var clauses = new List < string > ( ) ;
foreach ( var profile in qualitiesBelowCutoff )
{
foreach ( var belowCutoff in profile . QualityIds )
{
2020-01-01 21:46:33 +00:00
clauses . Add ( string . Format ( $"(\" { _table } \ ".\"ProfileId\" = {profile.ProfileId} AND \"MovieFiles\".\"Quality\" LIKE '%_quality_: {belowCutoff},%')" ) ) ;
2017-02-10 05:15:41 +00:00
}
}
return string . Format ( "({0})" , string . Join ( " OR " , clauses ) ) ;
}
2019-12-18 21:56:41 +00:00
public Movie FindByPath ( string path )
2019-12-22 21:24:10 +00:00
{
2019-12-18 21:56:41 +00:00
return Query ( x = > x . Path = = path ) . FirstOrDefault ( ) ;
2019-12-22 21:24:10 +00:00
}
2019-12-18 02:17:47 +00:00
2020-12-05 03:13:13 +00:00
public Dictionary < int , string > AllMoviePaths ( )
2019-12-18 02:17:47 +00:00
{
2019-12-18 21:56:41 +00:00
using ( var conn = _database . OpenConnection ( ) )
2019-12-18 02:17:47 +00:00
{
2022-03-28 20:45:52 +00:00
var strSql = "SELECT \"Id\" AS \"Key\", \"Path\" AS \"Value\" FROM \"Movies\"" ;
2020-12-05 03:13:13 +00:00
return conn . Query < KeyValuePair < int , string > > ( strSql ) . ToDictionary ( x = > x . Key , x = > x . Value ) ;
}
}
2020-09-04 02:50:56 +00:00
public List < int > AllMovieTmdbIds ( )
{
using ( var conn = _database . OpenConnection ( ) )
{
2022-03-20 15:55:47 +00:00
return conn . Query < int > ( "SELECT \"TmdbId\" FROM \"MovieMetadata\" JOIN \"Movies\" ON (\"Movies\".\"MovieMetadataId\" = \"MovieMetadata\".\"Id\")" ) . ToList ( ) ;
2020-09-04 02:50:56 +00:00
}
}
2020-11-27 05:36:18 +00:00
public Dictionary < int , List < int > > AllMovieTags ( )
{
using ( var conn = _database . OpenConnection ( ) )
{
2022-09-25 00:01:47 +00:00
var strSql = "SELECT \"Id\" AS \"Key\", \"Tags\" AS \"Value\" FROM \"Movies\" WHERE \"Tags\" IS NOT NULL" ;
2020-12-05 03:13:13 +00:00
return conn . Query < KeyValuePair < int , List < int > > > ( strSql ) . ToDictionary ( x = > x . Key , x = > x . Value ) ;
2020-11-27 05:36:18 +00:00
}
}
2020-09-04 02:50:56 +00:00
public List < int > GetRecommendations ( )
{
2020-12-21 21:28:35 +00:00
var recommendations = new List < int > ( ) ;
2020-09-04 02:50:56 +00:00
2021-01-30 19:40:44 +00:00
if ( _database . Version < new Version ( "3.9.0" ) )
{
return recommendations ;
}
2020-09-04 02:50:56 +00:00
using ( var conn = _database . OpenConnection ( ) )
{
2022-03-28 20:45:52 +00:00
if ( _database . DatabaseType = = DatabaseType . PostgreSQL )
{
recommendations = conn . Query < int > ( @"SELECT DISTINCT ""Rec" " FROM (
SELECT DISTINCT "" Rec "" FROM
2021-01-18 20:12:10 +00:00
(
2022-03-20 15:55:47 +00:00
SELECT DISTINCT CAST ( "" value "" AS INT ) AS "" Rec "" FROM "" MovieMetadata "" , json_array_elements_text ( ( "" MovieMetadata "" . "" Recommendations "" ) : : json )
WHERE CAST ( "" value "" AS INT ) NOT IN ( SELECT "" TmdbId "" FROM "" MovieMetadata "" union SELECT "" TmdbId "" from "" ImportExclusions "" as sub1 ) LIMIT 10
2022-03-28 20:45:52 +00:00
) as sub2
UNION
SELECT "" Rec "" FROM
(
2022-03-20 15:55:47 +00:00
SELECT CAST ( "" value "" AS INT ) AS "" Rec "" FROM "" MovieMetadata "" , json_array_elements_text ( ( "" MovieMetadata "" . "" Recommendations "" ) : : json )
WHERE CAST ( "" value "" AS INT ) NOT IN ( SELECT "" TmdbId "" FROM "" MovieMetadata "" union SELECT "" TmdbId "" from "" ImportExclusions "" as sub2 )
2022-03-28 20:45:52 +00:00
GROUP BY "" Rec "" ORDER BY count ( * ) DESC LIMIT 120
) as sub4
) as sub5
LIMIT 100 ; ").ToList();
}
else
{
recommendations = conn . Query < int > ( @"SELECT DISTINCT ""Rec" " FROM (
SELECT DISTINCT "" Rec "" FROM
(
2022-03-20 15:55:47 +00:00
SELECT DISTINCT CAST ( "" j "" . "" value "" AS INT ) AS "" Rec "" FROM "" MovieMetadata "" CROSS JOIN json_each ( "" MovieMetadata "" . "" Recommendations "" ) AS "" j ""
WHERE "" Rec "" NOT IN ( SELECT "" TmdbId "" FROM "" MovieMetadata "" union SELECT "" TmdbId "" from "" ImportExclusions "" ) LIMIT 10
2021-01-18 20:12:10 +00:00
)
UNION
2022-03-28 20:45:52 +00:00
SELECT "" Rec "" FROM
2021-01-18 20:12:10 +00:00
(
2022-03-20 15:55:47 +00:00
SELECT CAST ( "" j "" . "" value "" AS INT ) AS "" Rec "" FROM "" MovieMetadata "" CROSS JOIN json_each ( "" MovieMetadata "" . "" Recommendations "" ) AS "" j ""
WHERE "" Rec "" NOT IN ( SELECT "" TmdbId "" FROM "" MovieMetadata "" union SELECT "" TmdbId "" from "" ImportExclusions "" )
2022-03-28 20:45:52 +00:00
GROUP BY "" Rec "" ORDER BY count ( * ) DESC LIMIT 120
2021-01-18 20:12:10 +00:00
)
)
LIMIT 100 ; ").ToList();
2022-03-28 20:45:52 +00:00
}
2020-09-04 02:50:56 +00:00
}
2020-12-21 21:28:35 +00:00
return recommendations ;
2020-09-04 02:50:56 +00:00
}
2022-10-09 05:02:34 +00:00
public bool ExistsByMetadataId ( int metadataId )
{
var movies = Query ( x = > x . MovieMetadataId = = metadataId ) ;
return movies . Any ( ) ;
}
2016-12-29 15:04:01 +00:00
}
2017-02-23 05:03:48 +00:00
}