4

我有一个包含FULLTEXT 索引的列内容的表。

我想利用MATCH()处理大文本的速度。

我希望搜索尽可能准确。

当我以这种方式搜索短语字符串“大卡车”时:

SELECT * FROM MyTable WHERE MATCH(content) AGAINST('"large truck"' IN BOOLEAN MODE);

有些事例被遗漏了。

我的表:

|   content    |
----------------
|Large \n truck| FOUND ✓
----------------
|large truck   | FOUND ✓
----------------
|large trucks  | *PLURAL MISSED!
----------------
|large truckl  | *TYPE-O MISSED!

如果我使用标准的LIKE /通配符方法:

SELECT * FROM  `MyTable` WHERE  `content` LIKE  '%large truck%'

我的表:

|   content    |
----------------
|Large \n truck| *MISSED!
----------------
|large truck   | FOUND ✓
----------------
|large trucks  | FOUND ✓
----------------
|large truckl  | FOUND ✓

看来我也不能将 PHRASE 搜索与通配符一起使用:

SELECT * FROM MyTable WHERE MATCH(content) AGAINST('"large truck*"' IN BOOLEAN MODE); **DOES NOT WORK**

或者

SELECT * FROM MyTable WHERE MATCH(content) AGAINST('"large truck"*' IN BOOLEAN MODE); **DOES NOT WORK**

所以...

如何成功使用 MATCH() AGAINST() 搜索短语,并返回所有实例 - 甚至不区分大小写的部分字符串匹配?

4

2 回答 2

4

我经常使用 FT 的技巧是分两步完成:

  1. 做 a MATCH,希望得到所有想要的文本,但可能会有一些额外的结果。
  2. AND与另一个条件 - LIKE(更快)或REGEXP(更强大)。

因为 FT会MATCH很快;另一部分将第二次执行,所以它会很快,因为要检查的行不多。

这符合您的条件:

SELECT * FROM MyTable
    WHERE MATCH(content) AGAINST('+large +truck*' IN BOOLEAN MODE)
      AND content REGEXP "large[[:space:]]+truck";

换一种说法,查询将运行如下:

  1. 假设该表有 10K 行。
  2. 将评估 FT 表达式。这MATCH将非常快(因为它的设计方式)。它会在content. 现在,假设有 30 行满足这一要求。
  3. 其余的WHERE被评估。但它只针对那 30 行。因此,即使REGEXP成本高昂,也不会经常这样做。
  4. 然后可能返回 14 行。

最终效果是整个查询“快速”运行,这是您的要求之一。

注意:我需要第二部分来防止这些

large green truck
the truck is large

根据版本,您可能需要此 REGEXP "large\\s+truck"

于 2020-07-17T04:36:47.953 回答
1

这是 REGEXP 的快速破解,但它没有解决问题,因为它不使用全文索引:

SELECT * 
FROM MyTable 
WHERE content REGEXP("large[[:space:]]+truck*");

当然,您也可以通过不使用精确短语进行搜索来使用 FT 索引:

SELECT * 
FROM MyTable 
WHERE MATCH(content) AGAINST('+large +truck*' IN BOOLEAN MODE);

但这最终将包括您不想要的记录,因为它与精确短语搜索不同。

不幸的是,无论您使用 InnoDB 还是 MyISAM,短语搜索(双引号 - “”)和截断运算符(通配符 - *)都不起作用。它也不适用于InnoDB 的距离运算符(可能来自同一来源)。我想这与全文索引数据的存储方式有关。

于 2020-07-11T03:50:12.347 回答