MySQL 全文搜索功能

MySQLBeginner
立即练习

介绍

在本实验中,你将探索 MySQL 的全文搜索功能。你将首先创建一个名为 articles 的数据库和表,其中包含 idtitlecontent 列,然后用示例数据填充它。

接下来,你将使用 ALTER TABLE 语句为 articles 表添加一个名为 article_index 的全文索引,该索引将应用于 titlecontent 列。最后,你将使用 SHOW INDEXES 命令验证索引创建,确认 Index_typeFULLTEXT。此设置将为你准备好在 MySQL 数据库中进行高效的文本搜索。

在整个实验过程中,你将在 MySQL shell 中进行操作。你只需要在开始时进入 MySQL shell,并在最后退出。后续步骤中的所有 SQL 命令都应在同一个 MySQL 会话中执行。

创建数据库和表

在此步骤中,你将创建一个 MySQL 数据库和一张表来存储文章。这张表将用于演示全文搜索功能。

首先,打开你的终端并以 root 用户连接到 MySQL 服务器。你可以使用以下命令完成此操作:

sudo mysql -u root

此命令使用 root 用户连接到 MySQL 服务器。由于你使用了 sudo,系统不会提示你输入密码。

连接到 MySQL shell 后,你将看到 mysql> 提示符。在本次实验的后续所有步骤中,请保持在 MySQL shell 中,直到实验结束。

现在,让我们创建一个名为 search_db 的数据库。这个数据库将包含我们的 articles 表。执行以下 SQL 命令:

CREATE DATABASE IF NOT EXISTS search_db;

IF NOT EXISTS 子句确保仅在数据库不存在时才创建它。

接下来,使用 USE 命令切换到新创建的数据库:

USE search_db;

你应该会看到一条消息,表明数据库已更改。

现在,创建 articles 表。这张表将包含三个列:idtitlecontent

CREATE TABLE articles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT
);

让我们分解一下这个命令:

  • CREATE TABLE articles: 这个语句创建一个名为 articles 的新表。
  • id INT AUTO_INCREMENT PRIMARY KEY: 这定义了一个名为 id 的整数列,它为每一行自动递增,并作为表的主键。
  • title VARCHAR(255) NOT NULL: 这定义了一个名为 title 的字符串列,最大长度为 255 个字符。NOT NULL 表示此列不能为空。
  • content TEXT: 这定义了一个名为 content 的文本列,可以存储较长的字符串。

执行此命令后,articles 表将在 search_db 数据库中创建。

你可以通过列出当前数据库中的表来验证表的创建:

SHOW TABLES;

你应该会在输出中看到 articles

+-----------------------+
| Tables_in_search_db   |
+-----------------------+
| articles              |
+-----------------------+
1 row in set (0.00 sec)

现在你已经创建了数据库和表,可以准备在下一步中用一些示例数据填充它了。

插入示例数据并添加全文索引

在此步骤中,你将向 articles 表插入示例数据,然后添加一个全文索引以实现高效的文本搜索。

请确保你仍然在 MySQL shell 中并正在使用 search_db 数据库。如果不是,请选择该数据库:

USE search_db;

现在,让我们向 articles 表插入一些示例数据。我们将添加三行,包含不同的标题和内容:

INSERT INTO articles (title, content) VALUES
('MySQL Full-Text Search', 'This article explains how to use full-text search in MySQL.'),
('Indexing in MySQL', 'Learn about different types of indexes in MySQL, including full-text indexes.'),
('Optimizing MySQL Queries', 'Tips and tricks for optimizing your MySQL queries for better performance.');

这个 INSERT 语句向 articles 表添加了多行。VALUES 后面的每一组括号代表一个新行,其值对应于 titlecontent 列。

你可以通过选择表中的所有行来验证数据是否已插入:

SELECT * FROM articles;

你应该会在输出中看到已插入的三行:

+----+--------------------------+---------------------------------------------------------------------+
| id | title                    | content                                                             |
+----+--------------------------+---------------------------------------------------------------------+
|  1 | MySQL Full-Text Search   | This article explains how to use full-text search in MySQL.         |
|  2 | Indexing in MySQL        | Learn about different types of indexes in MySQL, including full-text indexes. |
|  3 | Optimizing MySQL Queries | Tips and tricks for optimizing your MySQL queries for better performance. |
+----+--------------------------+---------------------------------------------------------------------+
3 rows in set (0.00 sec)

现在表中有数据了,让我们添加一个全文索引。全文索引允许 MySQL 对文本数据执行快速且相关的搜索。我们将为 titlecontent 列都添加一个全文索引。

使用 ALTER TABLE 语句添加索引:

ALTER TABLE articles ADD FULLTEXT INDEX article_index (title, content);

让我们分解一下这个命令:

  • ALTER TABLE articles: 这表示我们正在修改 articles 表。
  • ADD FULLTEXT INDEX article_index: 这会添加一个类型为 FULLTEXT 的新索引,并将其命名为 article_index
  • (title, content): 这指定了将包含在全文索引中的列。

执行此命令后,MySQL 将在指定的列上构建全文索引。

要验证全文索引是否已成功创建,你可以使用 SHOW INDEXES 命令:

SHOW INDEXES FROM articles;

输出将显示 articles 表上的所有索引。你应该会看到 article_index 的一个条目,其 Index_type 列为 FULLTEXT

+----------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table    | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+----------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| articles |          0 | PRIMARY        |            1 | id          | A         |           3 |     NULL | NULL   |      | BTREE      |         |               | YES     | NULL       |
| articles |          1 | article_index  |            1 | title       | NULL      |           3 |     NULL | NULL   | YES  | FULLTEXT   |         |               | YES     | NULL       |
| articles |          1 | article_index  |            2 | content     | NULL      |           3 |     NULL | NULL   | YES  | FULLTEXT   |         |               | YES     | NULL       |
+----------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
3 rows in set (0.00 sec)

你现在已经成功插入了数据并为表添加了全文索引。在下一步中,你将学习如何使用此索引执行全文搜索。

执行基本全文搜索

在此步骤中,你将使用 MATCH AGAINST 子句在 articles 表上执行基本全文搜索。这是利用你创建的全文索引的基本方法。

请确保你仍然在 MySQL shell 中并正在使用 search_db 数据库。如果不是,请选择该数据库:

USE search_db;

MATCH AGAINST 子句用于 SELECT 语句的 WHERE 子句中。基本语法是:

SELECT column1, column2, ...
FROM table_name
WHERE MATCH (column_list) AGAINST ('search_term');

这里,column_list 是包含在全文索引中的列的逗号分隔列表(在我们的例子中是 titlecontent),而 'search_term' 是你要搜索的单词或短语。

让我们搜索包含单词 "MySQL" 的文章:

SELECT id, title, content FROM articles WHERE MATCH (title, content) AGAINST ('MySQL');

此查询从 articles 表中选择 idtitlecontent 列,其中 titlecontent 列匹配术语 "MySQL"。

你应该会看到以下输出:

+----+--------------------------+---------------------------------------------------------------------+
| id | title                    | content                                                             |
+----+--------------------------+---------------------------------------------------------------------+
|  1 | MySQL Full-Text Search   | This article explains how to use full-text search in MySQL.         |
|  2 | Indexing in MySQL        | Learn about different types of indexes in MySQL, including full-text indexes. |
|  3 | Optimizing MySQL Queries | Tips and tricks for optimizing your MySQL queries for better performance. |
+----+--------------------------+---------------------------------------------------------------------+
3 rows in set (0.00 sec)

所有三篇文章都会被返回,因为它们都包含单词 "MySQL"。

全文搜索还提供了一个相关性得分(relevance score),指示每行与搜索词的匹配程度。你可以在 SELECT 语句中包含此得分:

SELECT id, title, content, MATCH (title, content) AGAINST ('MySQL') AS relevance FROM articles;

此查询添加了一个名为 relevance 的列,显示每行的得分。

+----+--------------------------+---------------------------------------------------------------------+--------------------+
| id | title                    | content                                                             | relevance          |
+----+--------------------------+---------------------------------------------------------------------+--------------------+
|  1 | MySQL Full-Text Search   | This article explains how to use full-text search in MySQL.         | 1.34832763671875   |
|  2 | Indexing in MySQL        | Learn about different types of indexes in MySQL, including full-text indexes. | 0.5215404033660889 |
|  3 | Optimizing MySQL Queries | Tips and tricks for optimizing your MySQL queries for better performance. | 0.5215404033660889 |
+----+--------------------------+---------------------------------------------------------------------+--------------------+
3 rows in set (0.00 sec)

你可以按相关性对结果进行排序,以首先查看最佳匹配项:

SELECT id, title, content, MATCH (title, content) AGAINST ('MySQL') AS relevance FROM articles ORDER BY relevance DESC;

此查询根据 relevance 分数以降序对结果进行排序。

+----+--------------------------+---------------------------------------------------------------------+--------------------+
| id | title                    | content                                                             | relevance          |
+----+--------------------------+---------------------------------------------------------------------+--------------------+
|  1 | MySQL Full-Text Search   | This article explains how to use full-text search in MySQL.         | 1.34832763671875   |
|  2 | Indexing in MySQL        | Learn about different types of indexes in MySQL, including full-text indexes. | 0.5215404033660889 |
|  3 | Optimizing MySQL Queries | Tips and tricks for optimizing your MySQL queries for better performance. | 0.5215404033660889 |
+----+--------------------------+---------------------------------------------------------------------+--------------------+
3 rows in set (0.00 sec)

在此步骤中,你学习了如何使用 MATCH AGAINST 执行基本全文搜索,以及如何检索结果并按相关性排序。在下一步中,你将探索使用布尔模式(boolean mode)的更高级搜索选项。

使用布尔模式进行高级搜索

在此步骤中,你将使用 MATCH AGAINST 子句的布尔模式(boolean mode)来执行更精确和灵活的全文搜索。布尔模式允许你使用运算符来控制结果中必须或必须不包含的词语。

请确保你仍然在 MySQL shell 中并正在使用 search_db 数据库。如果不是,请选择该数据库:

USE search_db;

要使用布尔模式,你需要将 IN BOOLEAN MODE 子句添加到 MATCH AGAINST 语句中。语法是:

SELECT column1, column2, ...
FROM table_name
WHERE MATCH (column_list) AGAINST ('search_term' IN BOOLEAN MODE);

以下是一些在布尔模式中常用的运算符:

  • +: 要求结果中必须包含该词。
  • -: 排除包含该词的行。
  • "": 搜索精确短语。
  • *: 通配符运算符(放在词的末尾)。

让我们查找 必须 包含 "MySQL" 且 不得 包含 "optimizing" 的文章。

SELECT id, title, content FROM articles WHERE MATCH (title, content) AGAINST ('+MySQL -optimizing' IN BOOLEAN MODE);

此查询使用 + 运算符要求包含 "MySQL",并使用 - 运算符排除 "optimizing"。

你应该会看到以下输出:

+----+------------------------+---------------------------------------------------------------------+
| id | title                  | content                                                             |
+----+------------------------+---------------------------------------------------------------------+
|  1 | MySQL Full-Text Search | This article explains how to use full-text search in MySQL.         |
|  2 | Indexing in MySQL      | Learn about different types of indexes in MySQL, including full-text indexes. |
+----+------------------------+---------------------------------------------------------------------+
2 rows in set (0.00 sec)

关于 "Optimizing MySQL Queries" 的文章被排除了,因为它包含 "optimizing"。

现在,让我们搜索精确短语 "full-text search":

SELECT id, title, content FROM articles WHERE MATCH (title, content) AGAINST ('"full-text search"' IN BOOLEAN MODE);

使用双引号会搜索作为连续短语的词语。

输出将是:

+----+------------------------+---------------------------------------------------------------------+
| id | title                  | content                                                             |
+----+------------------------+---------------------------------------------------------------------+
|  1 | MySQL Full-Text Search | This article explains how to use full-text search in MySQL.         |
+----+------------------------+---------------------------------------------------------------------+
1 row in set (0.00 sec)

只有第一篇文章被返回,因为它包含精确短语 "full-text search"。

让我们尝试使用通配符运算符 *。假设你想查找包含以 "index" 开头的词的文章。

SELECT id, title, content FROM articles WHERE MATCH (title, content) AGAINST ('index*' IN BOOLEAN MODE);

index* 项将匹配 "index" 和 "indexing" 等词。

输出将是:

+----+------------------------+---------------------------------------------------------------------+
| id | title                  | content                                                             |
+----+------------------------+---------------------------------------------------------------------+
|  2 | Indexing in MySQL      | Learn about different types of indexes in MySQL, including full-text indexes. |
+----+------------------------+---------------------------------------------------------------------+
1 row in set (0.00 sec)

在此步骤中,你学习了如何使用 MATCH AGAINST 子句和各种运算符的布尔模式来执行更受控和特定的全文搜索。在下一步中,你将练习结合这些技术。

组合搜索技巧

在此步骤中,你将把基本的 MATCH AGAINST 搜索与布尔模式运算符结合起来,以执行更复杂和精细的全文本查询。

请确保你仍然在 MySQL shell 中并正在使用 search_db 数据库。如果不是,请选择该数据库:

USE search_db;

让我们尝试查找包含 "MySQL" 并且包含 "indexing" 或 "optimizing" 中任意一个词的文章。在布尔模式中,我们可以使用括号来组合可选的词语。

SELECT id, title, content FROM articles WHERE MATCH (title, content) AGAINST ('+MySQL +(indexing optimizing)' IN BOOLEAN MODE);

此查询要求包含 "MySQL" (+MySQL),并且要求括号内的词语至少包含一个 (+(indexing optimizing))。

输出将是:

+----+--------------------------+---------------------------------------------------------------------+
| id | title                    | content                                                             |
+----+--------------------------+---------------------------------------------------------------------+
|  2 | Indexing in MySQL        | Learn about different types of indexes in MySQL, including full-text indexes. |
|  3 | Optimizing MySQL Queries | Tips and tricks for optimizing your MySQL queries for better performance. |
+----+--------------------------+---------------------------------------------------------------------+
2 rows in set (0.00 sec)

第一篇文章被排除,因为它包含 "MySQL" 但不包含 "indexing" 或 "optimizing"。

你也可以将布尔模式与相关性得分(relevance scoring)结合起来。让我们查找包含 "MySQL" 的文章,并使用 > 运算符优先显示那些也提及 "indexing" 的文章。

SELECT id, title, content, MATCH (title, content) AGAINST ('+MySQL >indexing' IN BOOLEAN MODE) AS relevance FROM articles WHERE MATCH (title, content) AGAINST ('+MySQL >indexing' IN BOOLEAN MODE) ORDER BY relevance DESC;

此查询要求包含 "MySQL",并提高包含 "indexing" 的文章的相关性得分。然后根据计算出的相关性对结果进行排序。

输出将是:

+----+--------------------------+---------------------------------------------------------------------+-----------+
| id | title                    | content                                                             | relevance |
+----+--------------------------+---------------------------------------------------------------------+-----------+
|  2 | Indexing in MySQL        | Learn about different types of indexes in MySQL, including full-text indexes. |  1.6931  |
|  1 | MySQL Full-Text Search   | This article explains how to use full-text search in MySQL.         |  0.3068  |
|  3 | Optimizing MySQL Queries | Tips and tricks for optimizing your MySQL queries for better performance. |  0.3068  |
+----+--------------------------+---------------------------------------------------------------------+-----------+
3 rows in set (0.00 sec)

请注意,"Indexing in MySQL" 文章由于 >indexing 运算符而排名最高。

通过结合基本搜索、布尔运算符和相关性得分,你可以创建强大而灵活的全文本查询,以满足你的特定需求。

MySQL 全文搜索功能实验到此结束。你现在可以通过输入以下命令退出 MySQL shell:

exit

你已经学会了如何设置带全文索引的表、执行基本搜索以及使用布尔模式进行更高级的查询。

总结

在此次实验中,你学习了 MySQL 的全文搜索功能。你首先创建了一个名为 search_db 的数据库和一个名为 articles 的表来存储文本数据。然后,你用示例文章填充了该表。

关键步骤是使用 ALTER TABLE 语句为 articles 表的 titlecontent 列添加了一个名为 article_index 的全文索引。此索引对于高效的全文搜索至关重要。你使用 SHOW INDEXES 验证了索引的创建。

最后,你探索了如何使用 MATCH AGAINST 子句执行全文搜索。你学习了如何执行基本搜索、检索相关性得分以及按相关性对结果进行排序。你还深入研究了布尔模式,使用了 +-""* 等运算符来创建更精确和复杂的搜索查询。通过结合这些技术,你可以有效地搜索和检索存储在 MySQL 数据库中的文本数据。