2011-10-24 68 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()來確定分數。添加這些分數以獲得相關性。