1

在制定用于自动完成表单(jquery Axax + PHP)的查询时,我有一个关于 SQL 最佳实践的问题。

让我们假设以下内容:

  • 我有一个包含书名的数据库
  • 有些书的标题没有定冠词(“The”或“A”),例如“Life of Pi”
  • 有些书的标题带有定冠词(“The”或“A”),例如“The Catcher in the Rye”

结果,用户将在开头使用“The”或简单地省略“The”来输入书名并开始查询而没有任何定冠词。

似乎存在三个可能的查询:

SELECT 'title' FROM 'books' WHERE 'title' LIKE '%$string'

或者

SELECT 'title' FROM 'books' WHERE 'title' LIKE '$string%'

或者

SELECT 'title' FROM 'books' WHERE 'title' LIKE '%$string%'

当使用第一个查询方法(其中 % 在字符串之前)时,很难得到任何结果,因为字符串之前的通配符似乎表现错误。

使用第二个查询时,似乎更倾向于在标题前使用“The”进行完全匹配。因此,搜索“麦田里的守望者”的用户会找到这本书,但搜索“麦田里的守望者”的用户不会。

最后一个结果是最好的,因为它在字符串前后都有一个通配符。但是,它也给出了最长的自动完成列表。用户必须输入几个字母来缩小搜索结果的范围。

关于实现更有效查询的任何想法?或者第三种选择是最好的选择(因为将书名中的定冠词分开是不可行的?

提前致谢,

4

5 回答 5

2

您可以使用正则表达式进行搜索(查询结果很快)并且不要忘记为您的结果添加限制。

一个小例子

SELECT title FROM books WHERE title REGEXP '$string' LIMIT 20

或者你可以使用单词边界

SELECT title FROM books WHERE title REGEXP '[[:<:]]$string[[:>:]]' LIMIT 20

查看文档http://dev.mysql.com/doc/refman/5.5/en/regexp.html

于 2013-03-11T20:08:57.050 回答
1

我建议在字符串的任一侧使用带有通配符的第三种方法。如果您担心返回结果集的大小,也许将结果限制在一定数量,随着用户键入,列表自然会变得更小更具体。

于 2013-03-11T19:51:56.517 回答
1

您也可以考虑允许搜索仍然匹配的“Catcher Rye”。

在这种情况下 - 您将标记标题中的每个单词以及用户输入的单词并找到最佳匹配。

否则只有在输入 4 个或更多字符后才自动完成,并使用选项 3。

于 2013-03-11T19:52:36.730 回答
1
$query = mysqi_query("SELECT title FROM books WHERE title REGEXP '$string'");
if($query->num_rows() == 0) {

     //First remove all the stop words like for, the, of, a from the search string.
     $stopWords = array('/\bfor\b/i', '/\bthe\b/i', '/\bto\b/i', '/\bof\b/i','/\ba\b/i');
     $string = preg_replace($stopWords, "", $string);

     //Then, use 
     mysqli_query("SELECT title FROM books WHERE title REGEXP '$string'");
}
于 2013-03-11T20:15:32.363 回答
0

如果您担心建议的数量,您是否可以修改更改事件以仅在他们在字段中输入了一些最少字符数后才检索建议?

于 2013-03-11T19:50:22.280 回答