2011-10-24 70 views
0

我试图在MySQL中进行搜索,其中用户只有一个字段。该表是这样的:MySQL:使用MySQL相关搜索的特殊搜索算法

ID   BIGINT 
TITLE  TEXT 
DESCRIPTION TEXT 
FILENAME TEXT 
TAGS  TEXT 
ACTIVE  TINYINT 

现在,如果用户输入只是blah blubber,搜索必须请检查是否每一个字出现在田间地头TITLEDESCRIOTIONFILENAMETAGS。结果本身应该按相关性排序,因此字符串在记录中出现的频率如何。我得到这个示例数据:

ID | TITLE | DESCRIPTION | FILENAME | TAGS | ACTIVE 
1 | blah | blah   | bdsai | bdha | 1 
2 | blubber | blah   | blah  | adsb | 1 
3 | blah | dsabsadsab | dnsa  | dsa | 1 

在此示例中,ID 2必须在顶部(2×等等,1个脂),然后1(2×等等),然后加入3-(1X等等)。这个过程应该是动态的,所以用户也可以输入更多的单词,并且相关性与一个或几个单词相同。

这只能在MySQL中实现,还是必须使用一些PHP?这将如何工作?

非常感谢您的帮助!问候,弗洛里安

编辑:下面是结果后,我想汤姆苹果的答案:

我有四个记录看起来像这样:

ID | TITLE | DESCRIPTION | FILENAME | TAGS       | ACTIVE 
1 | s  | s   | s  | s        | 1 
2 | 0  | fdsadf  | sdfs  | a,b,c,d,e,f,s,a,a,s,s,as,sada | 1 
3 | 0  | s   | s  | s        | 1 
4 | a  | a   | a  | a        | 1 

现在,如果我搜索的字符串s,我只能得到排在前三位的记录,按s的相关性排序。这意味着,这些记录应该是订货这样的:

ID | TITLE | DESCRIPTION | FILENAME | TAGS       | ACTIVE 
2 | 0  | fdsadf  | sdfs  | a,b,c,d,e,f,s,a,a,s,s,as,sada | 1  <== 8x s 
1 | s  | s   | s  | s        | 1  <== 4x s 
3 | 0  | s   | s  | s        | 1  <== 3x s 

现在,我想我这样的查询(表名是PAGES):

select t . * 
    from (

     select 
       match(title) against('*s*' in boolean mode) 
      + match(description) against('*s*' in boolean mode) 
      + match(filename) against('*s*' in boolean mode) 
      + match(tags) against('*s*' in boolean mode) 
      as matchrank, 
       bb . * 
      from pages bb) t 
where t.matchrank > 0 
order by t.matchrank desc 

该查询返回的:

matchRank | ID | TITLE | DESCRIPTION | FILENAME | TAGS       | ACTIVE 
2   | 2 | 0  | fdsadf  | sdfs  | a,b,c,d,e,f,s,a,a,s,s,as,sada | 1 

这是因为通配符?我认为,字符串*s*也应该找到一个值,只有s ...

+0

事实证明,通配符解决方案对于ft_min_word_len设置不是有效的解决方法。最好的想法是将此设置更改为1并重新启动mysql。如果你不能用“LIKE”编写解决方法,但对于多于一个字符串和不到4个字符('S') –

回答

2

这可能会帮助你。它有点假设你的MySQL表使用MyISAM引擎,但:

create table blubberBlah (id int unsigned not null primary key auto_increment, 
title varchar(50) not null, 
description varchar(50) not null, 
filename varchar(50) not null, 
tags varchar(50)not null, 
active tinyint not null 
) engine=MyISAM; 

insert into blubberBlah (title,description,filename,tags,active) 
values ('blah','blah','bdsai','bdha',1); 
insert into blubberBlah (title,description,filename,tags,active) 
values ('blubber','blah','blah','adsb',1); 
insert into blubberBlah (title,description,filename,tags,active) 
values ('blah','dsabsadsab','dnsa','dsa',1); 

select t.* 
from 
(
select MATCH (title) AGAINST ('blubber blah' IN BOOLEAN MODE) 
     +MATCH (description) AGAINST ('blubber blah' IN BOOLEAN MODE) 
     +MATCH (fileName) AGAINST ('blubber blah' IN BOOLEAN MODE) 
     +MATCH (tags) AGAINST ('blubber blah' IN BOOLEAN MODE) as matchRank, 
     bb.* 
from blubberBlah bb 
) t 
order by t.matchRank desc; 

编辑

另一个假设,这种解决方案使是字符串,你对搜索长> = 4个字符。如果'搜索'字符串(即'blubber'或'blah')的长度可能为1,2或3个字符,那么您可以随时前往my.cnf文件并在[mysqld]配置选项下添加ft_min_word_len=1。然后重新启动MySQL,你应该很好去。

最后一件事:如果您正在考虑使用这种方法,那么您应该为每个列添加一个FULLTEXT INDEX。因此:

ALTER TABLE blubberBlah add fulltext index `blubberBlahFtIdx1`(`title`); 
ALTER TABLE blubberBlah add fulltext index `blubberBlahFtIdx2`(`description`); 
ALTER TABLE blubberBlah add fulltext index `blubberBlahFtIdx3`(`filename`); 
ALTER TABLE blubberBlah add fulltext index `blubberBlahFtIdx4`(`tags`); 

您可以找到布尔FULLTEXT更多的细节在MySQL Docs搜索。

+0

这对我不起作用 - 我总是得到一个matchRank 0 ... –

+0

您正在运行哪个版本的MySQL?你的matchRank值是0还是在我的答案中对你的表或示例表运行查询? –

+0

我正在运行5.0.45,我用我的^^替换了表名(“PAGES”) –

1

而不是搜索“在布尔模式下”,使用Match()Against()来确定分数。添加这些分数以获得相关性。