简体   繁体   English

MySQL-优化查询并返回更具体的匹配项

[英]MySQL - Optimizing my query and returning the more specific match

I posted a while back a question asking how to implement a search with the following criteria: 我不久前发布了一个问题,询问如何使用以下条件实施搜索:

On the "Searching" page, the customer can search for movies by any of the following attributes or their combination (logical "AND" operation):
title;
year;
director;
star's first name and/or last name. This means you need to do both: a) first name or last name if only one of the two names is provided; b) first name and last name, if both names are provided.

I then have to spit back out information about that movie from my database given the search input. 然后,根据搜索输入,我必须从数据库中吐出有关该电影的信息。 People suggested I use FullText Search, and I did. 人们建议我使用全文搜索,但是我做到了。 This is the solution I have come up with. 这是我想出的解决方案。

  String searchInput = request.getParameter("searchInput");
  String query = "";

  // First see if there is a number in their search
  // Note: doesn't consider more specific searches, because it only searches
  // based on the given number
  if (searchInput.matches("\\d+")) {
      Pattern p = Pattern.compile("\\d+");
      Matcher m = p.matcher(searchInput); 
      if (m.find()) {
          String number = m.group();
          int n = Integer.parseInt(number);
          query = "SELECT title, year, director, id " +
          "FROM movies " + 
          "WHERE year = " + n + " " +
          "OR title LIKE '%" + n + "%'";
      }
  } else {
      query = "SELECT title, year, director, r.id " +
      "FROM movies AS r, stars AS s " + 
      "WHERE MATCH(title, director) AGAINST('" + searchInput + "*') " + 
      "OR MATCH(first_name, last_name) AGAINST('" + searchInput + "*') " +
      "AND r.id IN (SELECT sim.movie_id " + 
                    "FROM stars_in_movies AS sim " + 
                    "WHERE sim.star_id = s.id " + 
                    "AND sim.movie_id = r.id) " +
      "GROUP BY title";
  }

  ResultSet rs = statement.executeQuery(query);

  // Query again, this time ANDing the matches to see if
  // there is a more specific search result
  Statement statement2 = dbcon.createStatement();
  query = "SELECT title, year, director, r.id " +
  "FROM movies AS r, stars AS s " + 
  "WHERE MATCH(title, director) AGAINST('" + searchInput + "*') " + 
  "AND MATCH(first_name, last_name) AGAINST('" + searchInput + "*') " +
  "AND r.id IN (SELECT sim.movie_id " + 
                "FROM stars_in_movies AS sim " + 
                "WHERE sim.star_id = s.id " + 
                "AND sim.movie_id = r.id) " +
  "GROUP BY title";

  ResultSet rs2 = statement2.executeQuery(query);
  if (rs2.next()) {
      // If there is a more specific match (ANDing the matches), use that instead
      rs2.beforeFirst();
      rs = rs2;
  }

Now, I know this is REALLY bad code, since I'm executing almost the same query twice, with the only difference being that I AND the matches in the second query. 现在,我知道这是非常糟糕的代码,因为我执行了几乎相同的查询两次,唯一的区别是我和第二个查询中的匹配项。 I can't seem to figure out a way to combine the two queries or also reduce the amount of matching done to speed up the query. 我似乎无法找出一种方法来组合两个查询或减少匹配量以加快查询速度。 I also don't have a good way to deal with the year of the movie that the user may or may not input. 对于用户可能输入或未输入的电影年份,我也没有很好的方法。

Here is what I have tried: 这是我尝试过的:

  1. I have tried searching up the FullText Search documentation for some functions that can be included in my search to make my SQL query return the more specific result if it matches more things, but the only thing that comes closest to such a thing is the Boolean Full-Text Search. 我尝试在FullText Search文档中搜索一些可以包含在我的搜索中的函数,以使我的SQL查询在匹配更多内容时返回更具体的结果,但是最接近这种情况的是Boolean Full。 -文本搜索。 However, I don't think I can use such a function because I have to distinguish between the different user's keyword inputs. 但是,我认为我不能使用这样的功能,因为我必须区分不同用户的关键字输入。

  2. I have also tried Googling AND/OR operations in MySQL that allows AND when possible, and if not possible, then ORs the query. 我还尝试了在MySQL中使用Google的AND / OR操作,该操作允许在可能的情况下进行AND操作,如果不可能,则对查询执行OR操作。 However, it doesn't seem possible to do this. 但是,似乎不可能做到这一点。

UPDATE: I have nested subqueries now and the search is MUCH faster. 更新:我现在嵌套了子查询,搜索速度更快。 However, I still need help with improving my code to return the more specific match and only the more specific match, if it exists. 但是,我仍然需要帮助改进我的代码以返回更具体的匹配,并且仅返回更具体的匹配(如果存在)。 Else, return the more general match (if anything at all matches). 否则,返回更一般的匹配项(如果所有匹配项都存在)。

Run each sub query separately. 分别运行每个子查询。 You can AND and OR results in code as required, assuming the size of the results are reasonable. 假设结果的大小合理,则可以根据需要对代码进行AND和OR运算。 Bit more coding, but you only run the necessary queries once. 更多的编码,但是您只运行必要的查询一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM