使用InnoDB引擎在全文搜索中使用连字符?

时间:2014-08-12 16:17:35

标签: php mysql sql full-text-search

我在零件编号表中进行了FULLTEXT搜索。一些部件号码有连字符。

表引擎是使用MySQL 5.6的InnoDB。

我遇到的问题是MySQL将连字符( - )字符视为单词分隔符。

所以我创建了一个新的MySQL charset排序规则,而连字符被视为一个字母。

我遵循了本教程:http://dev.mysql.com/doc/refman/5.0/en/full-text-adding-collation.html

我使用链接底部的语法创建了一个测试表,但是我使用了InnoDB引擎。我搜索了' ----'并收到"语法错误,意外' - '"

但是,如果我将引擎更改为MyISAM,我会得到正确的结果。

如何使用InnoDB引擎?

似乎MySQL向前迈进了一步又退了两步。

编辑:我找到了5.6(http://dev.mysql.com/doc/refman/5.6/en/full-text-adding-collation.html)的链接,这是使用InnoDB作为引擎的相同教程。

但这是我的考验:

create table test (a TEXT CHARACTER SET latin1 COLLATE latin1_fulltext_ci, FULLTEXT INDEX(a)) ENGINE=InnoDB

添加了一行只是" ----"

select * from test where MATCH(a) AGAINST('----' IN BOOLEAN MODE)

语法错误,意外' - '

放下桌子,MyISAM

create table test (a TEXT CHARACTER SET latin1 COLLATE latin1_fulltext_ci, FULLTEXT INDEX(a)) ENGINE=MyISAM

添加了一行只是" ----"

select * from test where MATCH(a) AGAINST('----' IN BOOLEAN MODE)

1结果

编辑2,如果它有助于直观地看到,那就是我的2个测试:

MyISAM

InnoDB

2 个答案:

答案 0 :(得分:0)

InnoDb FULLTEXT搜索可能将连字符视为停用词。因此,当它到达第二个连字符时,它会期望一个单词,而不是一个连字符。这可以解释'语法错误'。

为什么它在MyISAM中不这样做是因为InnoDB中FULLTEXT索引的实现完全不同,当然,它们只是在MySQL 5.6中为InnoDB添加。

你能做些什么?您似乎可以通过特殊表格来影响停用词列表:http://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_ft_user_stopword_table。这可能会阻止MySQL将连字符视为停用词。

答案 1 :(得分:0)

我最近遇到了这个确切的问题。我以前根据文档添加了自定义归类,并且正在使用MyISAM,并且运行良好。然后几周前切换到InnoDB,事情停止了。我尝试过:

  • 重建我的归类和A / B测试以确保它们正常工作
  • 通过将innodb_ft_enable_stopword设置为0来禁用停用词
  • 重建全文表和索引

最后,我采用了不同的方法,因为在全文索引方面,InnoDB似乎没有遵循与MyISAM相同的规则。这有点棘手,但适用于我的应用程序:

  1. 创建一个特殊的search列,其中包含我需要搜索的数据。该列具有全文索引,并且仅用于进行全文搜索而存在,在具有数百万行的表上,该列仍然非常快。
  2. 用我的-列中的所有search搜索/替换一个未使用的字符,该字符被视为“单词”字符。请参阅此处有关此问题:https://dba.stackexchange.com/questions/248607/which-characters-are-considered-word-characters。弄清楚什么字符不是那么容易,但是以下几个对我有用:Ω œ π µ。这些字符可能未在您需要搜索的数据中使用,但解析器会将它们识别为可搜索的字符。就我而言,我将-替换为Ω。由于我只需要行ID,因此人眼看不到此列中的数据是什么。
  3. 修订我的更新和插入内容,以使search列数据和替换保持最新。就我而言,这很容易,因为应用程序中只有一个地方可以更新此特定表。几个触发器也可以用来处理此问题:

    CREATE TRIGGER update_search BEFORE UPDATE ON animals
    FOR EACH ROW SET NEW.search = REPLACE(NEW.animal_name, '-', 'Ω');
    
    CREATE TRIGGER insert_search BEFORE INSERT ON animals
    FOR EACH ROW SET NEW.search = REPLACE(NEW.animal_name, '-', 'Ω');
    
  4. 在搜索查询中用-替换Ω

Voila。这是一个小提琴,演示:https://www.db-fiddle.com/f/x1WZpZP6wcqbTTvTEFFXYc/0

上述解决方法可能并不适用于每个应用程序,但希望对某些人有用。为InnoDB拥有一个真正的解决方案将是很棒的。