mysql布尔模式全文搜索通配符和文字

时间:2011-08-19 10:39:23

标签: mysql boolean wildcard full-text-search literals

我对MySQL全文搜索很新,我今天遇到了这个问题:

我的公司表在名称栏中有“e-magazine AG”的记录。我在名称列上有一个全文索引。

当我执行此查询时,找不到记录:

SELECT id, name FROM company WHERE MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE);

由于破折号我需要使用引号并使用通配符,因为我实现了“当您键入时搜索”功能。

当我搜索整个术语“电子杂志AG”时,会找到记录。

任何想法我在这里做错了什么?我读到有关将短划线添加到单词字符列表(需要配置更新)但我正在寻找一种以编程方式执行此操作的方法。

2 个答案:

答案 0 :(得分:3)

本条

MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE);

将搜索AND "e" AND NOT "magazi";即“e-magazi”中的-将被解释为not,即使它在引号内。
因此,它不会按预期工作。
解决方案是使用LIKE应用额外的having子句。

我知道这个having很慢,但它只会应用于匹配的结果,因此不应涉及太多行。

我建议像:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('magazine' IN BOOLEAN MODE)
HAVING name LIKE '%e-magazi%';

答案 1 :(得分:0)

MySQL全文将文本中的单词e-magazine视为短语,将视为单词。因此,它会产生两个emagazine。虽然它构建了搜索索引,但由于e(默认为4个字符),它不会将ft_min_word_len添加到索引中。

搜索查询使用相同的长度限制。这就是为什么搜索e-magazine会返回与a-magazine完全相同的结果的原因,因为完全忽略了a-

但现在你想找到确切的短语e-magazine。通过它你使用引号,这是找到短语的完整正确的方法,但MySQL不支持短语的运算符,仅支持单词:
https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html

  

使用此修饰符,某些字符在搜索字符串中单词的开头或结尾具有特殊含义

有些人会建议使用以下查询:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('e-magazi*' IN BOOLEAN MODE)
HAVING name LIKE 'e-magazi%';

正如我所说,MySQL忽略e-并搜索通配符magazi*。在获得这些结果后,它会使用HAVING来过滤e-magazi*的结果,包括e-。你会发现短语e-magazine AG。当然,只有在搜索短语包含通配符运算符且您不应该使用引号时才需要HAVING。此操作符由您的用户使用,而不是您!

注意:只要您不使用%包围搜索词组,它就会只找到以该词开头的字段。并且你不想包围它,因为它也会找到bee-magazine。因此,您可能需要额外的OR HAVING name LIKE ' %e-magazi%' OR HAVING NAME LIKE '\\n%e-magazi%'才能在文本中使用它。

<强>招

但最后我更喜欢一个技巧,所以根本不需要HAVING

  1. 如果您向数据库表添加文本,请将它们另外添加到单独的全文索引列中,并将up-to-date之类的单词替换为up-to-date uptodate
  2. 如果用户搜索up-to-date,请在查询中将其替换为uptodate
  3. 即便如此,您仍然可以在specific中找到user-specific,但up-to-date也可以找到date

    <强>加成

    如果用户搜索-well-known huge ports MySQL,则将其视为not include *well*, could include *known* and *huge*。当然,您也可以使用其他额外的查询变体来解决这个问题,但是使用上面的技巧可以删除连字符,因此搜索查询看起来就像这样:

    SELECT id
    FROM texts
    WHERE MATCH(text) AGAINST('-wellknown huge ports' IN BOOLEAN MODE)