用Java推荐电影

时间:2019-04-10 23:31:41

标签: java

我正在制作一个程序,可以在此程序的基础上,根据用户之前观看的电影(存储在数据库中),向用户推荐一些新电影。在这种情况下,我要考虑过去电影的类型,然后将其用于查找新电影(具有类似类型)。我现在遇到的问题是实现算法,这是到目前为止的代码

MovieWatchedDao.java

public Movie recommendMovie(String username) throws DaoException {

        Connection con = null;
        PreparedStatement ps = null;

        Movie m = null;
        String jsonStr = m.getGenre();
        String[] temp;
        String delimiter = ",";

        temp = jsonStr.split(delimiter);
        String genre = temp [0];
        String genre1 = temp [1];
        String genre2 = temp[2];

        try {
            String query = "SELECT * FROM MOVIES WHERE GENRE LIKE ? OR GENRE LIKE ? OR GENRE LIKE ? ";
            ps = con.prepareStatement(query);
            ps.setString(1, genre);
            ps.setString(2, genre1);
            ps.setString(3, genre2);
            ps.execute();

            System.out.println(query);
            System.out.println("Recommend movies");

        }catch (SQLException e)
        {
            throw new DaoException(e.getMessage());
        }

        return m;

    }

server.java

                    else if ("recommend".equals(command))
                    {
                        String username = tokens[1];
                        try {
                            Movie m = IMovieWatched.findMovieByUser(username);

                            //Get the genres
                            String jsonStr = m.getGenre();
//                          socketWriter.println(jsonStr);

                            String[] items = jsonStr.split(",");
                            List<String> itemList = Arrays.asList(items);
                            socketWriter.println(itemList);

                        }catch(DaoException e)
                        {
                            e.printStackTrace();
                        }
                    }

这里的想法是让用户键入 recommend tommy ,算法将从数据库中获取tommy观看过的电影列表,并收集这些电影的流派。然后,将具有相似类型的3部电影返回给用户。

2 个答案:

答案 0 :(得分:0)

如果我这样做的话,我会列出汤米已经看过的电影列表,然后通过计算汤米每个流派看过多少电影来浏览列表。他观看过的电影类型最多,然后我会从该类型的“数据库”中随机挑选3部电影。如果随机选择的电影在他的观看列表中,请选择该类型的另一部随机电影。当您挑选了3部电影时,将其退回。您可以通过多种方式执行此操作,我建议您查找Netflix的算法以推荐电影创意。

答案 1 :(得分:0)

根据观看一部或什至两部特定的电影,您不会对用户的电影喜欢不喜欢有太多了解。显然,您的建议只能基于以前观看过的电影类型。关于数据库中的电影以及用户观看的电影的信息越多,建议就越准确。您并不想仅根据流派来提出所有建议,在我认为重要的事情上有很多事情要考虑:

Genre
Genre Type 
Lead Actor
Year Created
Rating (Rotten Tomatoes Critics Consensus)
Director
Run Time
Watch time
Other cast members
Distributed by

例如,假设用户观看了名为 Top Gun 的电影(与Tom Cruise一起观看)。用户观看该影片之前 之后,这可能是数据列表。

Data Field       Before              After
==========================================
Title            Top Gun             Top Gun
Genre            Action              
Genre Type       Military Drama               
Lead Actor       Tom Cruise          
Year Created     1986                
Rating           83%                 
Director         Tony Scott          
Run Time         110 Minutes         
Watch Time (In User Table)           105 Minutes
Other Members    Kelly McGillis,     
                 Tom Skerritt,       
                 Val Kilmer,         
                 Anthony Edwards     
Distributed by   Paramount Pictures  
Date Watched (In User Table Only)    April 10, 2019
Times Watched (In User Table Only)   1

数据字段是数据库“电影”表字段,之前是“电影”表中的数据,之后是数据库中的相关字段用户表。在上面的示例中,我们可以清楚地看到用户在2019年4月10日观看了名为《壮志凌云》的电影,并且基本上一直观看到获得积分,这意味着他/她最有可能喜欢这部电影。如果观看时间=运行时间,则用户有可能离开播放电影的媒体设备或在电影播放期间入睡。如果该表显示该电影被观看了两次,则可以通过比较“观看时间”来降低该概率,并且可以显示用户更喜欢该电影的结果。

每个人都会喜欢他们喜欢的电影,他们观看的电影越多,您可以跟踪的数据越多,那么显然您的推荐就会越准确。

在这个特定时刻,您想保持简单,仅将建议基于Genre。首先,您需要维护一个用户数据库表,该表存储着用户名和他们观看的电影名,这些用户名和电影名也包含在电影表的数据库中:

用户表:

RowID        Long (Unique - AutoIncrement)
UserName     Text
UserID       Text
MovieName    Text
ReleaseDate  Date
DateWatched  Date
TimeStarted  Long
TimeEnded    Long

您现在需要在数据库中查询用户,并检索他/她观看的所有电影:

String sql = "SELECT DISTINCT MovieName From UsersTable WHERE UserName = ?;"

将ResultSet放入字符串数组(watchedMovies [])。现在查询数据库中的电影表,以检索用户观看的电影的所有不同流派:

// This is just a quick example....
StringBuilder criteria = new StringBuilder();
for (int i = 0; i < watchedMovies.length; i++) {
    criteria.append("MovieName = '").append(watchedMovies[i]).append("'");
    if (i != (watchedMovies.length - 1)) {
        criteria.append(" OR ");
    }
}

sql = "SELECT Genre FROM MoviesTable WHERE " + criteria.toString() + ";"

同样,将上述查询ResultSet中所有不同的Genre放入字符串数组(watchedGenres [])。 找到最受关注的流派。使用以下方法从字符串数组中获取该流派:

public static String mostFrequentElementInArray(String[] arr) {
    // Method returns the String element with highest frequency 

    // Create HashMap to store string elements and thier frequency 
    HashMap<String, Integer> hs = new HashMap<String, Integer>(); 

    // Iterate through array of strings 
    for (int i = 0; i < arr.length; i++) { 
        // If word already exist in HashMap then increase it's count by 1 
        if (hs.containsKey(arr[i])) { 
            hs.put(arr[i], hs.get(arr[i]) + 1); 
        } 
        // Otherwise add String element to HashMap 
        else { 
            hs.put(arr[i], 1); 
        } 
    } 

    // Create set to iterate over HashMap 
    Set<Map.Entry<String, Integer> > set = hs.entrySet(); 
    String key = ""; 
    int value = 0; 

    for (Map.Entry<String, Integer> me : set) { 
        // Check for String having highest frequency 
        if (me.getValue() > value) { 
            value = me.getValue(); 
            key = me.getKey(); 
        } 
    } 

    // Return String having highest frequency 
    return key; 
}

并使用此方法:

String recommendedGenre = mostFrequentElementInArray(watchedGenres);

现在,您可以查询数据库电影表以获取该特定类型的所有(或部分)电影:

sql = "SELECT * FROM MoviesTable WHERE Genre = '" + recommendedGenre + "';";

您想要的推荐的准确性取决于您存储的电影数据类型以及在 WHERE 子句条件下使用的电影数据,例如:

sql = "SELECT * FROM MoviesTable WHERE Genre = '" + recommendedGenre + "' AND GenreType = 'Military Drama';";

如果无法产生所需结果的数量,则将其降低到:

sql = "SELECT * FROM MoviesTable WHERE Genre = '" + recommendedGenre + "';";

将ResultSet放入字符串数组并将其显示给用户。如果愿意,您可以对Movies表中的大多数字段执行此操作,只需在 WHERE 子句中添加 AND 语句即可。您在 WHERE 子句中使用的标准越多,电影推荐的准确性就越高。

用户观看的电影越多,数据库就越会了解用户的喜好。最终可以确定用户仅观看其中有汤姆·克鲁斯的电影(出于某些未知原因)。 :)