2011-10-24 7 views
0

私はユーザーがただ1つのフィールドを持つMySQLで検索しようとしています。テーブルには、次のようになります。ユーザの入力だけでblah blubber、検索はすべての単語天気を確認する必要がある場合 MySQL:MySQL関連の検索を使用した特別な検索アルゴリズム

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

今すぐフィールド TITLEDESCRIOTIONFILENAMEまたは TAGSに表示されます。結果自体は関連性によって並べ替えられます。したがって、レコードに文字列が表示される頻度はどれくらいですか。私はこの例のデータ持っ:

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(2×何とか)、次いで3(1X何とか)。このプロセスは動的でなければならないので、ユーザーはさらに多くの単語を入力することができ、関連性は1つまたは複数の単語と同じように機能します。

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 

:私はトム・マックの答えを試みた後にここでの結果は次のとおりです。

私はこのように見える4つのレコードを持っていますs、私は3つのレコードを取得し、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文字以下でうまく動作しません。 –

答えて

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; 

EDIT

このソリューションが行うもう一つの仮定があることのためのあなたの検索は> = 4文字の長さの文字列。 'blubber'または 'blah'の検索文字列が1,2,3文字のいずれかになる可能性がある場合は、[mysqld]設定オプションの下でいつもmy.cnfファイルに行き、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`); 

あなたはBOOLEAN FULLTEXTの詳細はMySQL Docsで検索見つけることができます。

+0

これは私のためには機能しません - 私はいつもmatchRank 0を得ています... –

+0

あなたはどのMySQLのバージョンを実行していますか?あなたのテーブルまたは私の答えの例のテーブルに対してクエリを実行している0のmatchRankの値を取得しますか? –

+0

私は5.0.45を実行しています。私はtablenameを私の^^( "PAGES") –

1

「ブーリアンモード」で検索するのではなく、Match()Against()を使用してスコアを決定します。関連性を得るためにそれらのスコアを追加してください。

関連する問題