繁体   English   中英

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

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

我不久前发布了一个问题,询问如何使用以下条件实施搜索:

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.

然后,根据搜索输入,我必须从数据库中吐出有关该电影的信息。 人们建议我使用全文搜索,但是我做到了。 这是我想出的解决方案。

  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;
  }

现在,我知道这是非常糟糕的代码,因为我执行了几乎相同的查询两次,唯一的区别是我和第二个查询中的匹配项。 我似乎无法找出一种方法来组合两个查询或减少匹配量以加快查询速度。 对于用户可能输入或未输入的电影年份,我也没有很好的方法。

这是我尝试过的:

  1. 我尝试在FullText Search文档中搜索一些可以包含在我的搜索中的函数,以使我的SQL查询在匹配更多内容时返回更具体的结果,但是最接近这种情况的是Boolean Full。 -文本搜索。 但是,我认为我不能使用这样的功能,因为我必须区分不同用户的关键字输入。

  2. 我还尝试了在MySQL中使用Google的AND / OR操作,该操作允许在可能的情况下进行AND操作,如果不可能,则对查询执行OR操作。 但是,似乎不可能做到这一点。

更新:我现在嵌套了子查询,搜索速度更快。 但是,我仍然需要帮助改进我的代码以返回更具体的匹配,并且仅返回更具体的匹配(如果存在)。 否则,返回更一般的匹配项(如果所有匹配项都存在)。

分别运行每个子查询。 假设结果的大小合理,则可以根据需要对代码进行AND和OR运算。 更多的编码,但是您只运行必要的查询一次。

暂无
暂无

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

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