2011-08-19 104 views
6

我很新MySQL的全文搜索,我今天就遇到了这个问题:MySQL的布尔模式的全文搜索使用通配符和文字

我公司表中有“电子杂志AG”的记录中名称列。我在名称列上有一个全文索引。

当我执行这个查询记录中没有找到:

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

我需要由于仪表板的报价工作,因为我实现了一个“搜索您的输入”功能,使用通配符。

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

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

+0

有趣的问题。我可以在这里用一个像uuid字段的表格复制它。 'SELECT id,bootid FROM socket WHERE MATCH(bootid)AGAINST('+“18bda775”'BOOLEAN MODE);'会工作,如果我搜索“18bda775-711c”,但搜索“18bda”或“18bda775 -711“不起作用。有问题的'bootid'字段包含:18bda775-711c-4329-9de2-a3d81dc13d06 –

+0

我们也试图改变布尔控制字符,而不是使用# - 但它没有任何效果(是的,我修好了变更后的表索引) :'ft_boolean_syntax = +#><()〜*:“”&|' – hajo

回答

2

这一条款

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%'; 
+0

感谢您的信息,但它不帮助我,因为搜索字符串是由想要搜索公司的用户输入的。换句话说,执行查询的后端无法知道“e-magazi”是字符串“电子杂志”的一部分。搜索字段应该接受单词部分和完整单词。 – hajo

+0

过滤方法非常独特的方法!谢谢! – ProfileTwist

+0

你在哪里看到前面或搜索词组后的空白处? '+'是一个常规的全文操作符,而不是一个空格! – mgutt

0

MySQL的全文对待文本作为短语作为一个词的词e-magazine。因为它导致两个单词emagazine。虽然它建立搜索索引,但它不会将e添加到索引,因为ft_min_word_len(默认值为4个字符)。

搜索查询使用相同的长度限制。这就是为什么搜索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-。通过这你会发现短语e-magazine AG。当然,只有当搜索短语包含通配符运算符时,才需要使用HAVING,并且不应使用引号。这个操作符被你的用户使用,而不是你!

注:只要你不围绕搜索短语与%它会发现只有以该字开始的字段。而且你不想围绕它,因为它也会找到bee-magazine。所以也许你需要额外的OR HAVING name LIKE ' %e-magazi%' OR HAVING NAME LIKE '\\n%e-magazi%'才能在文本中使用它。

招数

但最后我更喜欢这样是不是需要在所有一招HAVING

  1. 如果添加文本到您的数据库表,另外将它们添加到一个单独的全文索引的列并用up-to-date uptodate替换up-to-date等词。
  2. 如果up-to-date用户搜索与uptodate取代它在查询中。

通过,你仍然可以找到user-specificspecificup-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)