文档首页
MySQL 8.4 参考手册
8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 97%

14.9.2 布尔全文搜索14.9.2 Boolean Full-Text Searches

MySQL can perform boolean full-text searches using the IN BOOLEAN MODE modifier. With this modifier, certain characters have special meaning at the beginning or end of words in the search string. In the following query, the +以及- operators indicate that a word must be present or absent, respectively, for a match to occur. Thus, the query retrieves all the rows that contain the word “MySQL” but that do 在多线程系统中 contain the word “YourSQL”:MySQL can perform boolean full-text searches using the IN BOOLEAN MODE modifier. With this modifier, certain characters have special meaning at the beginning or end of words in the search string. In the following query, the + and - operators indicate that a word must be present or absent, respectively, for a match to occur. Thus, the query retrieves all the rows that contain the word “MySQL” but that do not contain the word “YourSQL”:

mysql> SELECT * FROM articles WHERE MATCH (title,body)
    -> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+-----------------------+-------------------------------------+
| id | title                 | body                                |
+----+-----------------------+-------------------------------------+
|  1 | MySQL Tutorial        | DBMS stands for DataBase ...        |
|  2 | How To Use MySQL Well | After you went through a ...        |
|  3 | Optimizing MySQL      | In this tutorial, we show ...       |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ... |
|  6 | MySQL Security        | When configured properly, MySQL ... |
+----+-----------------------+-------------------------------------+
Note

在实现此功能时,MySQL 使用了有时称为 隐含布尔逻辑 的方法,其中In implementing this feature, MySQL uses what is sometimes referred to as implied Boolean logic, in which

  • + 代表 AND+ stands for AND

  • - 代表 NOT- stands for NOT

  • [无运算符] 表示 OR[no operator] implies OR

布尔全文搜索具有以下特性:Boolean full-text searches have these characteristics:

  • 它们不会自动按相关性递减顺序对行进行排序。They do not automatically sort rows in order of decreasing relevance.

  • InnoDB 表在执行布尔查询时,需要在 MATCH() 表达式的所有列上创建 FULLTEXT 索引。针对 MyISAM 搜索索引的布尔查询即使没有 FULLTEXT 索引也能工作,尽管以这种方式执行的搜索会相当慢。InnoDB tables require a FULLTEXT index on all columns of the MATCH() expression to perform boolean queries. Boolean queries against a MyISAM search index can work even without a FULLTEXT index, although a search executed in this fashion would be quite slow.

  • 最小和最大单词长度全文参数适用于使用内置 FULLTEXT 解析器和 MeCab 解析器插件创建的 FULLTEXT 索引。innodb_ft_min_token_size 和 innodb_ft_max_token_size 用于 InnoDB 搜索索引。ft_min_word_len 和 ft_max_word_len 用于 MyISAM 搜索索引。The minimum and maximum word length full-text parameters apply to FULLTEXT indexes created using the built-in FULLTEXT parser and MeCab parser plugin. innodb_ft_min_token_size and innodb_ft_max_token_size are used for InnoDB search indexes. ft_min_word_len and ft_max_word_len are used for MyISAM search indexes.

    最小和最大词长的全文参数不适用于使用 ngram 解析器创建的 FULLTEXT 索引。ngram 令牌大小由 ngram_token_size 选项定义。Minimum and maximum word length full-text parameters do not apply to FULLTEXT indexes created using the ngram parser. ngram token size is defined by the ngram_token_size option.

  • 停用词列表适用,由 innodb_ft_enable_stopword、innodb_ft_server_stopword_table 和 innodb_ft_user_stopword_table 控制 InnoDB 搜索索引,ft_stopword_file 控制 MyISAM 搜索索引。The stopword list applies, controlled by innodb_ft_enable_stopword, innodb_ft_server_stopword_table, and innodb_ft_user_stopword_table for InnoDB search indexes, and ft_stopword_file for MyISAM ones.

  • InnoDB全文搜索不支持在单个搜索词上使用多个操作符,例如:'++apple'。在单个搜索词上使用多个操作符会返回语法错误。MyISAM 全文搜索可以成功处理相同的搜索,忽略所有操作符,只考虑紧挨搜索词的操作符。InnoDB full-text search does not support the use of multiple operators on a single search word, as in this example: '++apple'. Use of multiple operators on a single search word returns a syntax error to standard out. MyISAM full-text search successfully processes the same search, ignoring all operators except for the operator immediately adjacent to the search word.

  • InnoDB全文搜索仅支持前置的加号或减号。例如,InnoDB支持'+apple',但不支持'apple+'。指定后置的加号或减号会导致InnoDB报告语法错误。InnoDB full-text search only supports leading plus or minus signs. For example, InnoDB supports '+apple' but does not support 'apple+'. Specifying a trailing plus or minus sign causes InnoDB to report a syntax error.

  • InnoDB 全文搜索不支持在通配符中使用前导加号('+*')、加号和减号的组合('+-')或前导加号和减号组合('+-apple')。这些无效查询会返回语法错误。InnoDB full-text search does not support the use of a leading plus sign with wildcard ('+*'), a plus and minus sign combination ('+-'), or leading a plus and minus sign combination ('+-apple'). These invalid queries return a syntax error.

  • InnoDB 全文搜索不支持在布尔全文搜索中使用 @ 符号。@ 符号保留用于 @distance 接近搜索运算符。InnoDB full-text search does not support the use of the @ symbol in boolean full-text searches. The @ symbol is reserved for use by the @distance proximity search operator.

  • 它们不使用适用于 MyISAM 搜索索引的 50% 阈值。They do not use the 50% threshold that applies to MyISAM search indexes.

布尔全文搜索功能支持以下运算符:The boolean full-text search capability supports the following operators:

  • +

    前置或后置的加号表示该词 必须 出现在返回的每一行中。InnoDB 仅支持前置加号。A leading or trailing plus sign indicates that this word must be present in each row that is returned. InnoDB only supports leading plus signs.

  • -

    前置或后置的减号表示该词必须 不 出现在返回的任何行中。InnoDB 仅支持前置减号。A leading or trailing minus sign indicates that this word must not be present in any of the rows that are returned. InnoDB only supports leading minus signs.

    注意:- 运算符仅用于排除那些原本可由其他搜索词匹配到的行。因此,一个布尔模式搜索如果只包含前置 - 的词,将返回空结果。它不会返回 “除包含任何被排除词的行之外的所有行。””Note: The - operator acts only to exclude rows that are otherwise matched by other search terms. Thus, a boolean-mode search that contains only terms preceded by - returns an empty result. It does not return “all rows except those containing any of the excluded terms.”

  • (无操作符)(no operator)

    默认情况下(当未指定+或-时),该词是可选的,但包含该词的行评分更高。这模拟了MATCH() AGAINST()在未使用IN BOOLEAN MODE修饰符时的行为。By default (when neither + nor - is specified), the word is optional, but the rows that contain it are rated higher. This mimics the behavior of MATCH() AGAINST() without the IN BOOLEAN MODE modifier.

  • @distance

    此操作符仅适用于InnoDB表。它用于测试两个或多个词是否都在指定的距离内开始,距离以词为单位。将搜索词放在紧挨着@distance操作符之前的双引号字符串中,例如,MATCH(col1) AGAINST('"word1 word2 word3" @8' IN BOOLEAN MODE)This operator works on InnoDB tables only. It tests whether two or more words all start within a specified distance from each other, measured in words. Specify the search words within a double-quoted string immediately before the @distance operator, for example, MATCH(col1) AGAINST('"word1 word2 word3" @8' IN BOOLEAN MODE)

  • > <

    这两个运算符用于改变一个单词对分配给行的相关性值的贡献。> 运算符增加贡献,而 < 运算符减少贡献。请参见此列表后的示例。These two operators are used to change a word's contribution to the relevance value that is assigned to a row. The > operator increases the contribution and the < operator decreases it. See the example following this list.

  • ( )

    括号将单词归入子表达式。括起来的组可以嵌套。Parentheses group words into subexpressions. Parenthesized groups can be nested.

  • ~

    开头的波浪符号表示否定运算符,会导致该词对该行相关性的贡献为负。这对于标记“噪声”词很有用。包含这种词的行评分比其他行低,但不会像使用-运算符那样完全排除。A leading tilde acts as a negation operator, causing the word's contribution to the row's relevance to be negative. This is useful for marking “noise” words. A row containing such a word is rated lower than others, but is not excluded altogether, as it would be with the - operator.

  • *

    星号作为截断(或通配符)运算符。与其他运算符不同,它是附加在要影响的词后面。如果词以*运算符前的词开头,则匹配成功。The asterisk serves as the truncation (or wildcard) operator. Unlike the other operators, it is appended to the word to be affected. Words match if they begin with the word preceding the * operator.

    如果一个单词使用了截断操作符,即使它太短或是停用词,它也不会从布尔查询中被删除。单词是否过短由 InnoDB 表的 innodb_ft_min_token_size 设置或 MyISAM 表的 ft_min_word_len 来确定。这些选项不适用于使用 ngram 分词器的 FULLTEXT 索引。If a word is specified with the truncation operator, it is not stripped from a boolean query, even if it is too short or a stopword. Whether a word is too short is determined from the innodb_ft_min_token_size setting for InnoDB tables, or ft_min_word_len for MyISAM tables. These options are not applicable to FULLTEXT indexes that use the ngram parser.

    带有通配符的单词被视为必须出现在一个或多个单词开头的前缀。如果最小单词长度为 4,则搜索'+word +the*'可能返回的行数少于搜索'+word +the',因为第二个查询会忽略长度过短的搜索词the。The wildcarded word is considered as a prefix that must be present at the start of one or more words. If the minimum word length is 4, a search for '+word +the*' could return fewer rows than a search for '+word +the', because the second query ignores the too-short search term the.

  • "

    用双引号(")括起来的短语只匹配包含该短语的行,完全按照输入的方式。全文本引擎会将短语拆分为单词,并在 FULLTEXT 索引中对这些单词执行搜索。非单词字符不需要完全匹配:短语搜索只要求匹配项包含与短语完全相同的单词并且顺序相同。例如,"test phrase" 会匹配 "test, phrase"。A phrase that is enclosed within double quote (") characters matches only rows that contain the phrase literally, as it was typed. The full-text engine splits the phrase into words and performs a search in the FULLTEXT index for the words. Nonword characters need not be matched exactly: Phrase searching requires only that matches contain exactly the same words as the phrase and in the same order. For example, "test phrase" matches "test, phrase".

    如果短语中不包含索引中的任何单词,则结果为空。单词可能不在索引中是由于多种因素的组合:如果它们在文本中不存在,是停用词,或者长度小于索引单词的最小长度。If the phrase contains no words that are in the index, the result is empty. The words might not be in the index because of a combination of factors: if they do not exist in the text, are stopwords, or are shorter than the minimum length of indexed words.

以下示例演示了一些使用布尔全文操作符的搜索字符串:The following examples demonstrate some search strings that use boolean full-text operators:

  • 'apple banana''apple banana'

    查找包含至少一个这两个单词的行。Find rows that contain at least one of the two words.

  • '+apple +juice''+apple +juice'

    查找包含两个单词的行。Find rows that contain both words.

  • '+apple macintosh''+apple macintosh'

    查找包含单词 “apple” 的行,但如果行中也包含 “macintosh”,则排名更高。Find rows that contain the word “apple”, but rank rows higher if they also contain “macintosh”.

  • '+apple -macintosh''+apple -macintosh'

    查找包含单词 “apple” 但不包含 “macintosh” 的行。Find rows that contain the word “apple” but not “macintosh”.

  • '+apple ~macintosh''+apple ~macintosh'

    查找包含单词“apple”的行,但如果该行还包含单词“macintosh”,则比行中不包含时评分更低。 这比“的搜索要”温和'+apple -macintosh',在“macintosh”存在时,该行将完全不会返回。Find rows that contain the word “apple”, but if the row also contains the word “macintosh”, rate it lower than if row does not. This is “softer” than a search for '+apple -macintosh', for which the presence of “macintosh” causes the row not to be returned at all.

  • '+apple +(>turnover <strudel)''+apple +(>turnover <strudel)'

    查找包含单词“apple”和“turnover”,或“apple”和“strudel”(顺序不限)的行,但将“apple turnover”排名高于“apple strudel”。Find rows that contain the words “apple” and “turnover”, or “apple” and “strudel” (in any order), but rank “apple turnover” higher than “apple strudel”.

  • 'apple*''apple*'

    查找包含如下单词的行:“apple”、“apples”、“applesauce”或“applet”。Find rows that contain words such as “apple”, “apples”, “applesauce”, or “applet”.

  • '"some words"''"some words"'

    查找包含精确短语 “some words” 的行(例如,包含 “some words of wisdom” 的行,但不包含 “some noise words” 的行)。请注意,括住短语的 " 字符是用于分隔短语的操作符字符。它们不是括住搜索字符串本身的引号。Find rows that contain the exact phrase “some words” (for example, rows that contain “some words of wisdom” but not “some noise words”). Note that the " characters that enclose the phrase are operator characters that delimit the phrase. They are not the quotation marks that enclose the search string itself.

InnoDB 布尔模式搜索的相关性排名Relevancy Rankings for InnoDB Boolean Mode Search

InnoDB 全文搜索是基于 Sphinx 全文搜索引擎建模的,其使用的算法基于 BM25 和 TF-IDF 排名算法。因此,InnoDB 布尔全文搜索的相关性排名可能与 MyISAM 的相关性排名不同。InnoDB full-text search is modeled on the Sphinx full-text search engine, and the algorithms used are based on BM25 and TF-IDF ranking algorithms. For these reasons, relevancy rankings for InnoDB boolean full-text search may differ from MyISAM relevancy rankings.

InnoDB 使用一种变体的 “词频-逆文档频率” (TF-IDF) 加权系统来为给定的全文搜索查询对文档的相关性进行排名。TF-IDF 加权基于一个词在文档中出现的频率,同时抵消该词在文档集合中出现的频率。换句话说,一个词在文档中出现得越频繁,并且在文档集合中出现得越少,该文档的排名就越高。InnoDB uses a variation of the “term frequency-inverse document frequency” (TF-IDF) weighting system to rank a document's relevance for a given full-text search query. The TF-IDF weighting is based on how frequently a word appears in a document, offset by how frequently the word appears in all documents in the collection. In other words, the more frequently a word appears in a document, and the less frequently the word appears in the document collection, the higher the document is ranked.

相关性排名的计算方式How Relevancy Ranking is Calculated

术语频率(TF)值是指一个词在文档中出现的次数。一个词的逆文档频率(IDF)值使用以下公式计算,其中 total_records 是集合中的记录总数,matching_records 是搜索词出现的记录数。The term frequency (TF) value is the number of times that a word appears in a document. The inverse document frequency (IDF) value of a word is calculated using the following formula, where total_records is the number of records in the collection, and matching_records is the number of records that the search term appears in.

${IDF} = log10( ${total_records} / ${matching_records} )  

当文档中某个单词出现多次时,IDF 值会乘以 TF 值:When a document contains a word multiple times, the IDF value is multiplied by the TF value:

${TF} * ${IDF}

使用 TF 和 IDF 值,可以使用以下公式计算文档的相关性排名:Using the TF and IDF values, the relevancy ranking for a document is calculated using this formula:

${rank} = ${TF} * ${IDF} * ${IDF}

该公式在以下示例中演示。The formula is demonstrated in the following examples.

单词搜索的相关性排名Relevancy Ranking for a Single Word Search

此示例演示了单词搜索的相关性排名计算。This example demonstrates the relevancy ranking calculation for a single-word search.

mysql> CREATE TABLE articles (
    ->   id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    ->   title VARCHAR(200),
    ->   body TEXT,
    ->   FULLTEXT (title,body)
    ->)  ENGINE=InnoDB;
Query OK, 0 rows affected (1.04 sec)

mysql> INSERT INTO articles (title,body) VALUES
    ->   ('MySQL Tutorial','This database tutorial ...'),
    ->   ("How To Use MySQL",'After you went through a ...'),
    ->   ('Optimizing Your Database','In this database tutorial ...'),
    ->   ('MySQL vs. YourSQL','When comparing databases ...'),
    ->   ('MySQL Security','When configured properly, MySQL ...'),
    ->   ('Database, Database, Database','database database database'),
    ->   ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
    ->   ('MySQL Full-Text Indexes', 'MySQL fulltext indexes use a ..');
Query OK, 8 rows affected (0.06 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> SELECT id, title, body, 
    ->   MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) AS score
    ->   FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+---------------------+
| id | title                        | body                                | score               |
+----+------------------------------+-------------------------------------+---------------------+
|  6 | Database, Database, Database | database database database          |  1.0886961221694946 |
|  3 | Optimizing Your Database     | In this database tutorial ...       | 0.36289870738983154 |
|  1 | MySQL Tutorial               | This database tutorial ...          | 0.18144935369491577 |
|  2 | How To Use MySQL             | After you went through a ...        |                   0 |
|  4 | MySQL vs. YourSQL            | When comparing databases ...        |                   0 |
|  5 | MySQL Security               | When configured properly, MySQL ... |                   0 |
|  7 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... |                   0 |
|  8 | MySQL Full-Text Indexes      | MySQL fulltext indexes use a ..     |                   0 |
+----+------------------------------+-------------------------------------+---------------------+
8 rows in set (0.00 sec)

总共有 8 条记录,其中有 3 条与“database”搜索词匹配。第一条记录(id 6)包含该搜索词 6 次,相关性排名为1.0886961221694946。该排名值是使用TF值 6(“database”搜索词在记录id 6中出现 6 次)和IDF值 0.42596873216370745 计算得出的,其计算方法如下(其中 8 是记录总数,3 是搜索词出现的记录数):There are 8 records in total, with 3 that match the “database” search term. The first record (id 6) contains the search term 6 times and has a relevancy ranking of 1.0886961221694946. This ranking value is calculated using a TF value of 6 (the “database” search term appears 6 times in record id 6) and an IDF value of 0.42596873216370745, which is calculated as follows (where 8 is the total number of records and 3 is the number of records that the search term appears in):

${IDF} = LOG10( 8 / 3 ) = 0.42596873216370745

然后将TF和IDF值代入排名公式:The TF and IDF values are then entered into the ranking formula:

${rank} = ${TF} * ${IDF} * ${IDF}

在 MySQL 命令行客户端中执行计算返回的排名值为 1.088696164686938。Performing the calculation in the MySQL command-line client returns a ranking value of 1.088696164686938.

mysql> SELECT 6*LOG10(8/3)*LOG10(8/3);
+-------------------------+
| 6*LOG10(8/3)*LOG10(8/3) |
+-------------------------+
|       1.088696164686938 |
+-------------------------+
1 row in set (0.00 sec)
Note

你可能会注意到,SELECT ... MATCH ... AGAINST 语句返回的排名值与 MySQL 命令行客户端 (1.0886961221694946 对比 1.088696164686938) 略有不同。差异是由于 InnoDB 在内部执行整数与浮点/双精度数之间的类型转换时(以及相关的精度和四舍五入决定)与在其他地方(如 MySQL 命令行客户端或其他类型计算器)执行方式不同造成的。You may notice a slight difference in the ranking values returned by the SELECT ... MATCH ... AGAINST statement and the MySQL command-line client (1.0886961221694946 versus 1.088696164686938). The difference is due to how the casts between integers and floats/doubles are performed internally by InnoDB (along with related precision and rounding decisions), and how they are performed elsewhere, such as in the MySQL command-line client or other types of calculators.

多词搜索的相关性排名Relevancy Ranking for a Multiple Word Search

此示例演示了基于前一个示例中使用的 articles 表和数据的多词全文搜索相关性排名计算方法。This example demonstrates the relevancy ranking calculation for a multiple-word full-text search based on the articles table and data used in the previous example.

如果搜索多个单词,相关性排名值是每个单词相关性排名值的总和,如下公式所示:If you search on more than one word, the relevancy ranking value is a sum of the relevancy ranking value for each word, as shown in this formula:

${rank} = ${TF} * ${IDF} * ${IDF} + ${TF} * ${IDF} * ${IDF}

对两个词('mysql tutorial')进行搜索返回以下结果:Performing a search on two terms ('mysql tutorial') returns the following results:

mysql> SELECT id, title, body, MATCH (title,body)  
    ->   AGAINST ('mysql tutorial' IN BOOLEAN MODE) AS score
    ->   FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+----------------------+
| id | title                        | body                                | score                |
+----+------------------------------+-------------------------------------+----------------------+
|  1 | MySQL Tutorial               | This database tutorial ...          |   0.7405621409416199 |
|  3 | Optimizing Your Database     | In this database tutorial ...       |   0.3624762296676636 |
|  5 | MySQL Security               | When configured properly, MySQL ... | 0.031219376251101494 |
|  8 | MySQL Full-Text Indexes      | MySQL fulltext indexes use a ..     | 0.031219376251101494 |
|  2 | How To Use MySQL             | After you went through a ...        | 0.015609688125550747 |
|  4 | MySQL vs. YourSQL            | When comparing databases ...        | 0.015609688125550747 |
|  7 | 1001 MySQL Tricks            | 1. Never run mysqld as root. 2. ... | 0.015609688125550747 |
|  6 | Database, Database, Database | database database database          |                    0 |
+----+------------------------------+-------------------------------------+----------------------+
8 rows in set (0.00 sec)

在第一条记录(id 8)中,'mysql' 出现一次,'tutorial' 出现两次。'mysql' 有六条匹配记录,'tutorial' 有两条匹配记录。当将这些值插入多词搜索的排名公式时,MySQL 命令行客户端返回的排名值符合预期:In the first record (id 8), 'mysql' appears once and 'tutorial' appears twice. There are six matching records for 'mysql' and two matching records for 'tutorial'. The MySQL command-line client returns the expected ranking value when inserting these values into the ranking formula for a multiple word search:

mysql> SELECT (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2));
+-------------------------------------------------------+
| (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2)) |
+-------------------------------------------------------+
|                                    0.7405621541938003 |
+-------------------------------------------------------+
1 row in set (0.00 sec)
Note

SELECT ... MATCH ... AGAINST 语句与 MySQL 命令行客户端返回的排名值之间的轻微差异,可以在前面的示例中找到解释。The slight difference in the ranking values returned by the SELECT ... MATCH ... AGAINST statement and the MySQL command-line client is explained in the preceding example.