mysql - 如何改善mysql NATURAL LANGUAGE MODE的搜索查询?

标签 mysql sql

这是我的查询

SELECT * FROM myTable WHERE MATCH (name) AGAINST ("Apple M1" IN NATURAL LANGUAGE MODE) 

如果我搜索Apple M1作为结果,则得到Orange M1,然后获得第三或更多位置,我得到Apple M-1 –这是我存储的值,我假设应该是第一个!

我的问题是:有没有一种方法可以微调mysql搜索?

最佳答案

他们改善MySQL自然语言模式搜索的最好方法是改用Boolean Full-Text Searches。它将与自然语言模式搜索相同,但是您可以使用其他修饰符来微调结果,例如通过

> <
这两个运算符用于更改单词对分配给行的相关性值的贡献。 >运算符增加贡献,而<运算符减小贡献。

有一个细微的差别,布尔模式搜索不会根据相关性自动排序,因此您必须自己进行排序。

SELECT * FROM myTable 
WHERE MATCH (name) AGAINST (">Apple M1" IN BOOLEAN MODE) 
ORDER BY MATCH (name) AGAINST (">Apple M1" IN BOOLEAN MODE) desc
并请注意:如果您与M-1匹配(即使最小字长设置为2),则两个版本的全文本搜索都不会找到M1。它只会寻找exakt(通常不区分大小写)的单词匹配,不会寻找相似的单词(除非使用*)。它会通过某种算法“仅”权衡(精确)单词的组合,如果使用它们,还会修饰修饰符。
更新根据注释进行一些补充说明:
如果您与Apple M1匹配,它将返回以任意顺序包含(不区分大小写)AppleM1的行,例如M1 appleApple M4Apple M-1Orange M1。找不到Apples M4Orange M-1,因为它们不是那个单词。例如。 like '%M-1%'也找不到Apple M1。但是,如果愿意,您可以与Apple*匹配以找到AppleApples,但这始终位于单词的末尾,不可能使用*Apple*,则必须使用like '%Apple%'
然后,根据评分算法对这些行进行排序,从本质上说,这些单词将对您的文本中不常见的单词进行评分,而对非常常见的单词进行评分。如果添加>Apple,它将为Apple赋予更高的值。这只是一个数字,您可以将其添加到您的选择中,例如select ..., MATCH (name) AGAINST (">Apple M1" IN BOOLEAN MODE) as score对此有所了解。
还有其他一些事情要考虑:
  • 仅将具有最小长度的单词添加到索引中。该长度由用于innodb的innodb_ft_min_token_size或对于myisam的ft_min_word_len给出。所以您应该将其设置为2包括M1(否则,该单词对您的搜索不会有任何影响。由于在您的示例中,您发现Orange M1,因此我认为它设置正确)。
  • -通常被视为连字符。因此,您文本中的M-1将分为两个单词M1(根据您的最小单词长度设置,可能会或可能不会包含,因此请将其设置为1)。您可以通过向字符集添加-来更改该行为(请参阅Fine-Tuning MySQL Full-Text Search,以Modify a character set file开头的部分),但是如果您搜索blue-green和/或blue,则此方法将不再找到green
  • 全文搜索使用stopwords。这些词不包括在您的索引中。此列表包括ai,因此即使最小字长为1,您也不会找到它们。您可以编辑该列表。

  • 有关您可能会遇到的M1 / M-1问题的一些想法。要根据您的确切要求进行调整,您必须添加有关搜索和数据的更多信息(可能是另一个问题),但有一些建议:
  • 您可以通过将两个版本都包含在搜索查询中来替换包含-的用户输入:一次用-,但用""括起来,一次不使用。因此,如果用户输入Apple M-1,则将创建一个Apple M1 "M-1"的搜索(无论有没有经过修改的字符集都可以使用,但是没有新的字符集,您的最小字长必须为1)。如果用户输入M1,那么您应该检测到该位置并将其替换为M1 "M-1"
  • 另一种选择是使用干净的,无连字符的单词保存其他列,并将该列添加到全文索引中,然后添加到match (name, clean_name) against ("M1" ...中。
  • 当然,您可以将喜欢和匹配相结合,例如如果您在输入中检测到产品编号,则可以使用where match(...) against(...) or product_id like 'M%1%'where match(...) against(...) or product_id = 'M-1' or product_id = 'M1'甚至where match(...) against(...) or name like '%M%1%'之类的东西,但是后者可能会变慢得多并且包含很多噪音。而且它可能得分不正确,但是至少它将在结果集中。

  • 但是正如我所说,那将取决于您的数据和您的要求。

    关于mysql - 如何改善mysql NATURAL LANGUAGE MODE的搜索查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37577774/

    相关文章:

    mysql - 为什么不像memcached那样使用MySQL呢?

    php - 计算两个时间戳之间每个用户的记录数

    java - 无法从数据库填充产品数组

    mysql - 完成学业的学生文件如何处理

    sql - Groovy,如何进行两阶段提交?在Sql.withTransaction中可以跨多个数据库管理transactionscope吗?

    php - 在 php 中创建相关的帖子脚本 - 不是 Wordpress

    php - SQL : Join not working

    mysql - 在执行 INNER JOIN 时使用 IN 插入获取不同的值

    python - 安装 MySQL Python(在 Windows 7 上)

    php - 将 $item = mysql_fetch_assoc($stmt) 更改为准备语句样式