MySQL 布尔全文搜索
MySQL布尔全文搜索是MySQL中的一种额外形式的全文搜索。它比自然语言搜索更加以单词为导向,这意味着它搜索的是单词而不是概念。它允许我们根据非常复杂的查询进行搜索,包括布尔运算符,如小于(<)或大于(>)运算符,加号(+)和减号(-),子表达式(“(“和”)”),双引号(“”),一个降低值对结果贡献的运算符(~)以及通配符。
因此,这种搜索模式适合有经验的用户,因为它提供了执行一些非常高级的搜索的手段。我们可以在此模式下执行全文搜索,方法是在AGAINST函数中包括 IN BOOLEAN MODE修饰符 。
让我们通过一个基本示例来理解它。假设我们有一个名为 posts 的表,其中包含以下数据:
以下是一个关于如何搜索包含“Java”单词的帖子标题的结果示例:
mysql> SELECT id, title FROM posts
WHERE MATCH(title, descriptions)
AGAINST('Java' IN BOOLEAN MODE);
执行查询将返回包含Java单词的两个帖子名:
假设我们想要获取帖子名称中包含“MySQL”单词但不包含任何其他包含“Java”单词的行。在这种情况下,我们可以使用排除布尔运算符(-)来获得所需的输出。请看以下查询:
mysql> SELECT id, title FROM posts
WHERE MATCH (title, descriptions)
AGAINST ('MySQL -Java' IN BOOLEAN MODE);
执行查询将返回包含MySQL单词而不是Java单词的帖子名称:
重要性分数
MATCH()函数为表中的每一行分配了一个相关性值,并按照最高相关性优先进行排序。 最高相关性排在首位 。该值确定其与搜索词的相关性。相关性分数始终是 非负浮点数 。
如果我们想要检查文本相关性并按照最高相关性优先对行进行排序,可以使用以下查询:
mysql> SELECT title, MATCH (title, descriptions)
AGAINST ('Java, Workbench' IN BOOLEAN MODE) AS relevance_score
FROM Posts WHERE MATCH (title, descriptions)
AGAINST ('Java, Workbench' IN BOOLEAN MODE);
执行查询,我们将获得期望的结果:
以下是另一个示例,列出每一行的相关性值,即使值为零的情况下也是如此。在 WHERE子句中 ,我们可以得到这个结果而不使用MATCH()函数。下面是语句:
mysql> SELECT title, MATCH (title, descriptions)
AGAINST ('Java, Workbench' IN BOOLEAN MODE) AS relevance_score
FROM Posts;
执行查询,我们将得到所需的结果:
MySQL布尔全文搜索运算符
该表显示了在全文布尔搜索模式下使用的运算符及其含义:
运算符 | 描述 |
---|---|
+ |
返回的每一行必须包含一个前导或尾随的加号,表示搜索字符串。 |
- |
返回的任何行中不能包含一个前导或尾随的减号,表示搜索字符串。 |
> |
用于改变单词对行的相关值的贡献。大于运算符增加相关值。 |
< |
用于改变单词对行的相关值的贡献。小于运算符减少相关值。 |
* |
表示单词末尾的通配符。 |
~ |
充当否定运算符,否定单词的排序值。在标记噪声词中非常有用。 |
"" |
定义由双引号字符(”)括起来的短语。它匹配整个短语,而不是个别单词。 |
() |
括号运算符用于将单词分组为子表达式。它们可以嵌套并允许作为一个组包含、排除、排名等等。 |
@distance |
仅在InnoDB表中使用,测试两个或更多单词是否在指定的距离内起始。 |
没有运算符 | 如果我们既没有使用加号也没有使用减号运算符,默认情况下,该单词是可选的,但评级较高。 |
让我们看一些示例,说明在搜索查询中使用布尔全文运算符的用法 :
1. 如果我们想要搜索包含以下单词之一的行: Java或tutorial ,我们可以使用下面的语句:
mysql> SELECT id, title FROM posts
WHERE MATCH(title, descriptions)
AGAINST('Java tutorial' IN BOOLEAN MODE);
2. 如果我们想要搜索同时包含以下两个词或短语的行: Java和tutorial , 我们可以使用以下语句:
mysql> SELECT id, title FROM posts
WHERE MATCH(title, descriptions)
AGAINST('+Java +tutorial' IN BOOLEAN MODE);
3. 如果我们想要搜索包含单词Java的行,但对包含MySQL的行给予更高的优先级: 高级排名
mysql> SELECT id, title FROM posts
WHERE MATCH(title, descriptions)
AGAINST('+Java tutorial' IN BOOLEAN MODE);
4. 如果我们想要搜索包含单词Java的行,但对于包含MySQL的行,我们将给予它们 较低的排名 :
mysql> SELECT id, title FROM posts
WHERE MATCH(title, descriptions)
AGAINST('+Java ~tutorial' IN BOOLEAN MODE);
5. 如果我们想要找到包含以”my”开头的单词的行,比如”MySQL”,我们可以使用以下查询:
mysql> SELECT id, title FROM posts
WHERE MATCH(title, descriptions)
AGAINST('My*' IN BOOLEAN MODE);
MySQL布尔完全文本搜索特性
- MySQL布尔完全文本搜索不会自动按照相关性递减的顺序对行进行排序。
- 如果我们想在InnoDB表中执行布尔查询,需要在MATCH表达式的所有列上都建立全文索引。然而,在MyISAM表中这不是必需的,但搜索会变慢。
- InnoDB表上的全文搜索不支持在一个单词上使用多个布尔运算符,例如,’+database’。如果我们这样做,MySQL会返回语法错误。然而,在忽略其他运算符并使用与搜索词相邻的运算符的MyISAM表中可以进行处理;例如,’+-database’将变为’-database’。
- InnoDB全文搜索仅支持前导加号(+)或减号(-),不能有尾随的加号或减号。如果我们这样做,MySQL会报告语法错误。例如,我们可以在InnoDB中搜索’+database’但不能搜索’database-‘。此外,我们也不能将前导加号或减号与通配符字符一起使用:+*、+-等等。
- MySQL会忽略搜索结果中的50%阈值(单词出现在超过50%的行中)。
- MySQL InnoDB全文搜索允许在布尔完全文本搜索中使用@符号。