MySql `MATCH AGAINST` 和 `LIKE` 组合搜索特殊字符
Posted
技术标签:
【中文标题】MySql `MATCH AGAINST` 和 `LIKE` 组合搜索特殊字符【英文标题】:MySql `MATCH AGAINST` and `LIKE` combination to search for special characters 【发布时间】:2021-12-20 11:58:30 【问题描述】:例如,在数据库中,我有一个带有短语 DN-NP
的行。
在输入字段中,我输入 DN-
并希望找到该行。
这是示例http://sqlfiddle.com/#!9/f9235a/4
尝试使用FULLTEXT
索引和MATCH AGAINST
SELECT `name`
FROM `domains`
WHERE MATCH (`name`) AGAINST ('DN*' IN BOOLEAN MODE);
没有结果。
这里https://dba.stackexchange.com/a/111895/55397 建议与LIKE
结合使用。目前的想法是在 php 中类似于
if( strlen($_POST['input_field_value']) <= 2 )
$sql = 'SELECT `name`
FROM `domains`
WHERE MATCH (`name`) AGAINST ('DN*' IN BOOLEAN MODE)
OR `name` LIKE "%DN%"';
但是 LIKE "% %" 太慢了?任何想法如何解决问题(查找包含特殊字符的短语)?
LOCATE
(性能)呢?
SELECT name AS name7
FROM domains
WHERE LOCATE('DN',`name`)>0;
【问题讨论】:
【参考方案1】:索引可以通过限制查看的行数来帮助提高速度。到目前为止显示的大多数代码都需要测试每一行。
FULLTEXT
非常擅长在其规则适用时查找行。由于字长和标点符号的存在,我怀疑+DN*
是否适用。
`LIKE "DN-NP%" 可以非常有效地使用索引。但这仅适用于列开头的字符串。
`LIKE "%DN-NP%" -- 前导通配符需要检查每一行。
LOCATE
和任何其他字符串运算符 -- 不可 sargable,因此需要查看每一行。
REGEXP "DN-NP" -- slower than
LIKE. (There are other situations where
REGEXPcan be faster and/or
LIKE` 不适用。)
如果您将最小字长设置为 2,那么这个技巧可能是最有效的:
WHERE MATCH(col) AGAINST("+DN +NP" IN BOOLEAN MODE)
AND col LIKE '%DN-NP%'
MATCH
将有效地减少行数; LIKE
将进一步减少数字或行数,但只查看MATCH
中的小数字。
警告:你需要匹配哪些不匹配?:
abc DN-NP def
abc DNs-NPed def -- look likes "plural", etc which FULLTEXT matches
abc DN-NPQRS def -- word boundary issue
abc ZYXDN-NP def
REGEXP
可以匹配“单词边界”; LIKE
没有这样的。
请建立一个你想要匹配/不匹配的列表。我们可能会为您提供更好的答案。
【讨论】:
感谢您的建议。在输入字段中我输入DN
我想在mysql 中查找包含...的行实际上我想在任何位置找到包含DN
的所有行(所有四个示例)。如果在输入字段中输入DN-
,我还想在任何位置找到包含DN-
的所有mysql 行。我的意思是,我想找到所有包含输入字符串(字符)的行
在sqlfiddle.com/#!9/28a3f3/9 中继续测试。似乎MATCH
的问题是,如果在输入字段中输入-
字符,那么IN BOOLEAN MODE
表示NOT
。没有BOOLEAN MODE
,什么都得不到。 LIKE
和 %...%
正是我需要的。但据我所知,如果有很多行,速度太慢了。所以问题是如何减少LIKE
的行数。有趣的信息在这里***.com/a/41716705/2118559“我想评论一下,在我的案例中,创建索引还有助于加快类似 '%abc%' 的查询。”
@Andris - SHOW VARIABLES LIKE 'innodb_ft_min_token_size';
可能是 3,这意味着 DN
太短而无法编入索引。
是的,正确,最小值是 3。得到了[0] => Array ( [Variable_name] => innodb_ft_min_token_size [Value] => 3 )
@Andris - 如果将该设置更改为 2,则需要重新创建索引才能生效。【参考方案2】:
正则表达式怎么样?
选择名称作为名称6
来自域
WHERE name
regexp ('DN');
【讨论】:
以上是关于MySql `MATCH AGAINST` 和 `LIKE` 组合搜索特殊字符的主要内容,如果未能解决你的问题,请参考以下文章
MySQL MATCH() AGAINST() 等效于 SQL Server
MySql `MATCH AGAINST` 和 `LIKE` 组合搜索特殊字符