2013-07-03 11 views
7

私はDB上で全文検索を行う検索クエリを持っています。私は「カルドソ、オラシオ」または「カルドソ」または「オラシオ」を検索すると複数の列にわたるMySQLフルテキスト検索:結果の混乱

$sql = "SELECT 
* 
FROM 
`tbl_auction_listing` AS `al` 
JOIN 
`tbl_user` AS `u` ON `al`.`user_id` = `u`.`user_id` 
LEFT JOIN 
`tbl_gallery_details` AS `gd` ON `al`.`user_id` = `gd`.`user_id` 
LEFT JOIN 
`tbl_self_represented_details` AS `sr` ON `u`.`user_id` = `sr`.`user_id` 
WHERE 
`al`.`status` = '" . ACTIVE . "' 
AND 
`al`.`start_date` < NOW() 
AND 
`al`.`end_date` > NOW() 
AND 
MATCH(`al`.`listing_title`, 
`al`.`description`, 
`al`.`provenance`, 
`al`.`title`, 
`al`.`artist_full_name`, 
`al`.`artist_first_name`, 
`al`.`artist_last_name`, 
`sr`.`artist_name`, 
`gd`.`gallery_name`, 
`u`.`username`) AGAINST('$search_query' IN BOOLEAN MODE)"; 

私は結果を得るていない、しかし私はartist_full_name =カルドソ、オラシオとデシベルでの2つのレコードのアーティストが存在しているはず。

すべての一致フィールドを削除して、ちょうどalがある場合。 artist_full_name私は2つの結果が得られます。私がalに追加した場合。 description説明に「Horacio Cardozo」が存在するため、1つの結果が得られます。

MATCHフィールドのいずれかで条件(検索クエリワード)が満たされていると、検索ですべてのレコードを返す方法はありますか? IN BOOLEAN MODEを取り除こうとしましたが、同じ結果が出ました。

+0

'IN BOOLEAN MODE'の代わりに' NATURAL LANGUAGE MODE'を試してください –

+0

'NATURAL LANGUAGE MODE'はデフォルトモードです(モードが指定されていない場合) – RandomSeed

+0

検索時に0の結果が得られます。私は、DBのすべてのフィールドがフルテキストであることを確認しましたが、まだ何もありません。 – puks1978

答えて

15

InnoDBテーブルでは、同じMATCH()の条件で複数のフルテキストインデックスを検索することはできません。

ここで、フィールドはすべて同じテーブルに属しているわけではないため、異なるインデックスで扱われています。 、

CREATE TABLE t (
    f1 VARCHAR(20), 
    f2 VARCHAR(20), 
    FULLTEXT(f1), FULLTEXT(f2) 
) ENGINE=InnoDB; 

SELECT * FROM t 
WHERE MATCH(f1, f2) AGAINST ('something in f2'); -- likely to return no row 

は、全文検索が唯一それがに遭遇した最初のフルテキストインデックスで検索可能と同じように見えますが、これは私がfrom this experienceを差し引くだけで何かですしてください:あなたはこのようなテーブルがあった場合にも、同じ制限が適用されます注意してくださいこれを当然とみなさないでください。これは、あなたがauctionと1の2つの別々のインデックスを持っていた場合は可能なクエリの説明図である

SELECT * FROM auction, user, gallery, ... 
WHERE 
    MATCH(auction.field1, auction.field2) AGAINST ('search query' IN BOOLEAN MODE) OR 
    MATCH(auction.field3) AGAINST ('search query' IN BOOLEAN MODE) OR 
    MATCH(user.field1, user.field2, user.field3) AGAINST... 

bottomlineはMATCH()句ごとに1つのフルテキストインデックスを使用するように、あなたの検索を分割すべきであるということです1つはuserです。あなたは実際の構造にそれを適応させる必要があります(詳細なガイダンスが必要な場合はテーブルの説明を記入してください)。

これはInnoDBテーブルにのみ適用されます。興味深いことに、MyISAMテーブルdo not seem to show the same limitation


更新:それは5.6.13/5.7.2で修正され、これはa bug in the InnoDB engineだっ判明。上記の例は、 "列リストに一致するFULLTEXTインデックスが見つかりません"という正当な理由で失敗します。実際、(f1, f2)にはインデックスがありませんが、(f1)(f2)にあるインデックスはありません。 As the changelog advises:MyISAMテーブルとは異なり

、InnoDBは 索引なしの列にブール全文検索をサポートしていませんが、この制限は、誤った結果が返されたクエリで をその結果、施行されていませんでした。

このようなクエリはMyISAMで正しい結果セットを返しますが、予想よりも遅く実行されます(they silently ignore existing fulltext indexes)。

+0

私は*を使ってその単語の後に何かを得ることができますが、単語の途中で検索クエリが始まるかもしれない単語を得る方法がありますか?たとえば、次のような検索条件が返されます。 – puks1978

+0

'... WHERE field LIKE '%pple''('% 'はワイルドカード)ですが、このようなクエリはフルテキストインデックスを使用できません通常のインデックスも同様)。 "[列がインデックスの一番左のプレフィックスを形成しない場合、MySQLはインデックスを使用できません](http://dev.mysql.com/doc/refman/5.6/en/mysql-indexes.html)"(このステートメントは最初は複数列インデックスを記述することを意図していましたが、部分インデックスの場合は実際は同じ考えです)。 – RandomSeed

+0

'where'節に複数の' match ... or match ... 'セクションを使用することをお勧めしますmyisamがインデックスを使用するのを妨げるようです。 'union'を使った独立したクエリがうまく動作します。 E、g、 'select * from rsspodcastitems("野菜 ")とのマッチタイトル、または"野菜 "とのマッチ - > 16行(2.46秒)' select * from rsspodcastitems where match title against( " "野菜")union select * from rsspodcastitems( "vegetables") - > 16行(0.02秒) 'にマッチするサブタイトル。 – Jules

関連する問題