【问题标题】:MySql `MATCH AGAINST` and `LIKE` combination to search for special charactersMySql `MATCH AGAINST` 和 `LIKE` 组合搜索特殊字符
【发布时间】: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;

【问题讨论】:

    标签: mysql sql-like match-against


    【解决方案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/orLIKE` 不适用。)

    如果您将最小字长设置为 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 的行数。有趣的信息在这里stackoverflow.com/a/41716705/2118559“我想评论一下,在我的案例中,创建索引还有助于加快类似 '%abc%' 的查询。”
    • @Andris - SHOW VARIABLES LIKE 'innodb_ft_min_token_size'; 可能是 3,这意味着 DN 太短而无法编入索引。
    • 是的,正确,最小值是 3。得到了[0] =&gt; Array ( [Variable_name] =&gt; innodb_ft_min_token_size [Value] =&gt; 3 )
    • @Andris - 如果将该设置更改为 2,则需要重新创建索引才能生效。
    【解决方案2】:

    正则表达式怎么样?

    选择名称作为名称6 来自域 WHERE name regexp ('DN');

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-12
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      相关资源
      最近更新 更多