2013-07-03 45 views
7

我有一个搜索查询,它在数据库上执行全文搜索。对多列进行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)"; 

当我搜索“卡多佐,奥拉西奥”或“卡多佐”或“奥拉西奥”我得到的却没有结果,我知道有2条记录与artist_full_name =卡多佐,奥拉西奥分贝的艺术家。

如果我删除所有MATCH字段并且只有alartist_full_name我收到2条结果。如果我加入aldescription我得到1个结果,因为'Horacio Cardozo'存在于描述中。

如果在任何MATCH字段中遇到任何条件(任何搜索查询词),是否有方法让搜索返回所有记录?我试图删除布尔模式,但产生了相同的结果。

+0

而不是'IN BOOLEAN MODE',尝试'IN NATURAL LANGUAGE MODE' –

+0

'IN 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什么东西,请不要认为这是理所当然的。

的底线是,你应该分裂您的搜索,按MATCH()子句中使用一个单一的全文索引:

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... 

这是一个可能的查询的说明,如果你对auction和一个两个不同的指标一个在user。你需要适应你的实际结构(如果你需要更多的指导,请张贴你的表的描述)。

注意这只适用于InnoDB表格。有趣的是,MyISAM表do not seem to show the same limitation


更新:原来这是a bug in the InnoDB engine,固定在5.6.13/5.7.2。上面的例子现在正确地失败了,“无法找到匹配列列表的FULLTEXT索引”。事实上,(f1, f2)上没有索引,但(f1)上的索引和(f2)上的索引中没有索引。 As the changelog advises

不同的MyISAM,InnoDB的不支持 非索引列布尔全文搜索,但这一限制没有得到执行,导致返回不正确的结果的查询 。

值得注意的是,尽管这样的查询返回正确的结果于MyISAM集,它们运行比人们预期的要慢,因为they silently ignore existing fulltext indexes

+0

我可以使用*来获取该单词之后的任何内容,但是有没有办法获得搜索查询可能在单词中间开始的单词?例如:query = pple返回结果'apple' – puks1978

+0

您可以使用搜索条件,例如:... WHERE field LIKE'%pple''('%'是通配符),但是这样的查询不能使用全文索引也不是常规指数)。 “[如果列没有形成索引的最左边的前缀,MySQL不能使用索引](http://dev.mysql.com/doc/refman/5.6/en/mysql-indexes.html)”(这个语句是最初是为了描述多列索引,但对于部分索引来说它确实是一样的想法)。 – RandomSeed

+0

您在'where'子句中使用多个'match ...或match ...'部分的建议似乎也会阻止myisam使用索引。具有'union'的独立查询效果更好。 E,g,'select * from rsspodcastitems where match title against(“vegetables”)or match subtitle against(“vegetables”) - > 16 rows in set(2.46 sec)''而select * from rsspodcastitems where match title against “蔬菜”)union select * from rsspodcastitems其中匹配字幕(“蔬菜”) - > 16行(0.02秒)'。 – Jules