使用多个单词搜索MYSQL并通过相关性进行排序

时间:2013-06-10 00:03:57

标签: php mysql

我正在PHP中创建一个用户提交文件的程序,然后可以根据他们最初创建文件时输入的6个类别来搜索该文件。这些类别存储在一个单元格的表格中,如下所示:            category_1 category_2 category_3 etc - 它们不在单独的列中

我需要创建一个页面,用户可以在其中填写要搜索的类别,然后将查询提交给MYSQL数据库。我希望页面对文件首先与大多数类别匹配的行进行排序。

我的问题是如何设置MYSQL查询以搜索6个类别,然后按匹配最多类别的行排序结果(在匹配2个类别的前面显示3个匹配类别之一?

我会提出我尝试的代码,但我甚至不知道从哪里开始(我是否使用正则表达式?)。任何帮助都会很棒。我熟悉PHP和HTML,但MYSQL对我来说是新的。

3 个答案:

答案 0 :(得分:0)

你应该调查在布尔模式下使用MySQL的FULLTEXT搜索。

http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html

特别是当您将类别连接在一个列中时,这很可能是解决问题的好方法。

您需要使用MyISAM作为您以这种方式搜索的表格的访问方法。

(注意:如果不使用布尔模式,全文搜索很难在小桌子上进行测试;它对小文本语料库的单词频率的感知会产生不可预测的结果。但是使用布尔模式你会没事的。 )

答案 1 :(得分:0)

让我们说这些类别位于名为@Categories的列中。为方便起见,我将假设它们以逗号分隔,而不是以空格分隔(您可以在以下代码中使用replace)。这简化了解释。

select
from files f
order by (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 1))), ',' 1), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 2)), ',' 1)), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 3)), ',' 1)), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ', ', 4), ',' 1)), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 5)), ',' 1)), f.categories) > 0) +
      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', 6)), ',' 1)), f.categories) > 0) desc

(注意:这是未经测试的。)

关键是表达式:

      (find_in_list(reverse(substring_index(reverse(substring_index(@Categories, ',', <n>)), ',' 1)), f.categories) > 0) +

让我们从里面解释一下:

表达式substring_index(@Categories, ',', <n>)返回类别字符串,直到第n个类别。

reverse然后反转这个字符串,所以第n个现在是第一个。

下一个substring_index返回此字符串的第一个元素,即原始字符串的第n个元素。但是,它是相反的,因此下一个reverse。最后,find_in_set()在文件的类别中查找此内容。

整个order by子句将这些值加在一起(布尔值在MySQL中加起来像整数)。因此,您可以获得匹配的数量 - 这就是您想要订购原始数据的方式。

所有这一切,这是一个糟糕的数据结构。如果您以更标准化的形式存储它,解决方案会更容易。

答案 2 :(得分:0)

这应该适合你:

 select 
    id, 
    name, sum(
       IF(find_in_set('$cat1', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat2', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat3', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat4', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat5', replace(' ',',','categories'), 1, 0) +
       IF(find_in_set('$cat6', replace(' ',',','categories'), 1, 0)) as match_score
 from products
    where match_score > 0 
 order by match_score desc;