2011-10-24 1 views
0

사용자가 하나의 필드 만 가지고있는 MySQL에서 검색을 시도하고 있습니다. 표는 다음과 같습니다 : 사용자의 입력이 단지 blah blubber, 검색은 모든 단어 어떠했는지를 확인해야하는 경우 MySQL : MySQL 관련 검색을 사용하는 특수 검색 알고리즘

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

지금 필드 TITLE, DESCRIOTION, FILENAME 또는 TAGS에 나타납니다. 결과 자체는 관련성에 따라 정렬되어야하므로 레코드에 문자열이 얼마나 자주 표시되는지. I이 예 데이터를 얻었다 :

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 × ㅋ, 1X 두툼한)이어야 후 1 (배 ㅋ), 그리고 (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 

: I는 다음과 같이 네 개의 레코드가

: 여기 결과는 내가 톰 맥의 대답을 시도 이후 s, 나는 s의 관련성에 따라 정렬 된 상위 3 개의 레코드 만 가져야합니다. 이 기록이 같은 주문자해야 의미 :

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 
:

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 

이 쿼리는이를 반환 : 이제

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입니다)이처럼 내 쿼리를 시도

와일드 카드 때문입니까? 제 생각에는 문자열 *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 자 길이가 될 가능성이있는 경우 항상 012.c32f의 머리글을 사용하여 [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`); 

당신은 MySQL Docs에서 검색 BOOLEAN FULLTEXT에 대한 자세한 내용을 확인할 수 있습니다.

+0

이것은 나를 위해 작동하지 않습니다 - 나는 항상 matchRank 0을 얻고 있습니다 ... –

+0

MySQL 버전을 실행하고 있습니까? 당신은 당신의 테이블 또는 내 응답에서 예제 테이블에 대한 쿼리를 실행하는 0의 matchRank 값을 얻나요? –

+0

5.0.45를 실행 중입니다. tablename을 ^^ ("PAGES") –

1

'부울 모드에서'검색하는 대신 Match() Against()를 사용하여 점수를 결정하십시오. 관련성을 얻기 위해 점수를 더하십시오.