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...AGAINSTLIKE 组合在一起,而不进行全表扫描:

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 不会归档 xyzdc10LIKEs 会。 带有前导通配符的LIKE需要进行全表扫描。 您正在使用OR

因此是表扫描。

相反,如果您只想dc10 开头的词,那么请去掉LIKEs——MATCH 可以完成所有工作,而且速度很快。

FULLTEXT 索引将列分成单词,然后搜索单词。 LIKE 没有;相反,它必须扫描每个字符串。没有索引好处 LIKE 带有初始通配符。

【讨论】:

以上是关于MySQL 部分单词匹配结合 MATCH...AGAINST 和 LIKE 作为备份的主要内容,如果未能解决你的问题,请参考以下文章

MySQL MATCH() AGAINST() FULLTEXT Index - 结合短语匹配实现部分字符串匹配

我怎样才能找到部分单词匹配/找到c ++

MySQL - 如何使用 LIKE 搜索精确的单词匹配?

使用正则表达式匹配MYSQL中句子中的单词

从输入字段中查找部分单词匹配,我还发现来自 HTML 代码的结果。为啥?

在 Excel 中的 2 列之间提取部分匹配字符串(单词)