MySQL 部分单词匹配结合 MATCH...AGAINST 和 LIKE 作为备份
Posted
技术标签:
【中文标题】MySQL 部分单词匹配结合 MATCH...AGAINST 和 LIKE 作为备份【英文标题】:MySQL partial word match combining MATCH...AGAINST and LIKE as backup 【发布时间】:2018-10-12 10:49:57 【问题描述】:MATCH...AGAINST
在布尔模式下的 mysql 文档说类似“星号用作截断(或通配符)运算符。与其他运算符不同,它附加到要影响的单词。单词匹配如果它们以* 运算符前面的单词。”这意味着您只能使用它来匹配单词的开头。我希望能够尽可能高效地搜索,有时我正在搜索的单词是目标字符串中间的部分单词。我试图避免在不需要时进行全表扫描。
有没有办法将MATCH...AGAINST
语法与WHERE foo LIKE '%bar%
的备份相结合?
例如,我有下表(为简洁起见省略了一堆字段):
CREATE TABLE `tours` (
`tourId` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`tourName` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`tourId`),
FULLTEXT KEY `ft_tourId_tourName` (`tourName`,`tourId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
我希望能够在单个查询中同时搜索 tourId 和 tourName,仅在绝对必要时才进行全表扫描。
是否可以做这样的事情,我将MATCH...AGAINST
和LIKE
组合在一起,而不进行全表扫描:
SELECT
*
FROM
tap.tourdetails
WHERE
MATCH(tourId, tourName) AGAINST('dc10*' IN BOOLEAN MODE)
OR tourId LIKE '%dc10%' OR tourName LIKE '%dc10%' ORDER BY tourName;
目前,即使 'dc10*' 在 MATCH...AGAINST
中实际匹配,上面也会进行全表扫描。如果 MATCH 失败,我只想使用LIKE
(和所需的全表扫描)。可能的?替代解决方案?
【问题讨论】:
在开头使用带有通配符的LIKE
通常需要进行全表扫描。
我明白这一点。如果MATCH...AGAINST
条件成功,我问有没有办法避免它。
不清楚你的意思是什么“即使'dc10*'
实际上是匹配的”:MySQL没有办法从找到一个全文搜索match
那里赢了'不是额外的like
匹配。 (实际上,这是另一种方式:match against
在这里似乎是多余的(使用这些搜索词),因为like
将再次找到与match against
相同的行,但反之则不然)。您可能想准确解释您的意思或您正在尝试做的事情;也许您只对查找 any 感兴趣,而不是 all 结果(但这不等同于您当前的搜索结果)。
我想尽可能避免全表扫描,因为它非常慢。我想要的是作为匹配找不到结果时的后备。
【参考方案1】:
假设您希望找到xyzdc10
:
MATCH
不会归档 xyzdc10
但 LIKEs
会。
带有前导通配符的LIKE
需要进行全表扫描。
您正在使用OR
。
因此是表扫描。
相反,如果您只想以dc10
开头的词,那么请去掉LIKEs
——MATCH
可以完成所有工作,而且速度很快。
FULLTEXT
索引将列分成单词,然后搜索单词。 LIKE
没有;相反,它必须扫描每个字符串。没有索引好处 LIKE
带有初始通配符。
【讨论】:
以上是关于MySQL 部分单词匹配结合 MATCH...AGAINST 和 LIKE 作为备份的主要内容,如果未能解决你的问题,请参考以下文章
MySQL MATCH() AGAINST() FULLTEXT Index - 结合短语匹配实现部分字符串匹配