MySQL 关键词搜索:任意顺序完全匹配方案
2024-12-27 04:54:41
MySQL 搜索:关键词任意顺序但需完全匹配
搜索功能是网站的重要组成部分。有时,需求是查找包含多个关键词,并且这些关键词的出现顺序不重要的记录。数据库查询应该如何优化,以确保返回的结果是完全匹配关键词,哪怕顺序不同? 这篇文章深入探讨该问题,并给出一些实践方法。
问题分析
代码段展示了常见的搜索逻辑:将输入的关键词使用空格分割,然后针对每个词进行模糊匹配(LIKE %keyword%
)。 这种方式确实会返回包含任何 一个关键词的记录,而并非必须包含所有 关键词。
因此,blue car
作为查询,它会查找包含 blue
或者 car
的所有条目。这与需求:需要同时包含 blue
和 car
,无论它们的顺序是不同的。
解决方案
这里有几种解决方案来达成要求,每个方案都有其侧重点和应用场景。
1. 使用 AND
连接 LIKE
条件
将所有关键词的匹配条件用 AND
连接,可以确保记录同时包含所有关键词,而不再是仅仅包含其中之一。
function search_it() {
if (isset($_GET['s'])) {
global $wpdb;
$address_table = $wpdb->prefix . 'my_products';
$search = $_GET['s'];
$search = trim($search);
$keywords = explode(" ", $search);
$where_conditions = [];
foreach ($keywords as $keyword) {
$keyword = "%{$keyword}%";
$where_conditions[] = $wpdb->prepare('(name LIKE %s OR price LIKE %s OR id LIKE %s OR market_price LIKE %s OR image_url LIKE %s)',$keyword,$keyword, $keyword, $keyword,$keyword );
}
if(empty($where_conditions)) {
return [];
}
$where = "WHERE " . implode(" AND ", $where_conditions);
$results = $wpdb->get_results( "SELECT * FROM {$address_table} {$where} LIMIT 0,30" );
return $results;
}
}
操作步骤:
- 修改
search_it()
函数:不再是迭代keywords
生成最终where
子句,改为循环构建匹配条件。 - 构建的每个匹配条件使用
prepare
防止SQL注入,并使用OR逻辑合并字段的搜索结果。 - 使用
implode(" AND ", $where_conditions)
将匹配条件数组使用AND
连接成完整的WHERE
子句。 - 将新的
WHERE
子句嵌入SQL语句执行查询,并返回结果。
这种方案利用 AND
条件保证所有关键词都出现在搜索结果中,可以满足基本的关键词任意顺序匹配需求。不过模糊匹配也会增加不必要的匹配,导致搜索结果有偏差。
2. 使用 FULLTEXT
索引与 MATCH ... AGAINST
对于需要高效率搜索大量文本的场景,MySQL 的 FULLTEXT
索引是个很好的选择。
首先需要在表上建立全文索引:
ALTER TABLE `my_products` ADD FULLTEXT(`name`, `price`,`id`,`market_price`,`image_url`);
或者也可以通过下面的命令创建一个索引,如果之前已经存在需要drop:
ALTER TABLE my_products DROP INDEX your_index_name;
CREATE FULLTEXT INDEX your_index_name ON my_products (`name`,`price`,`id`,`market_price`,`image_url`);
your_index_name
是你希望命名的索引名字。
然后,在 PHP 代码中使用 MATCH ... AGAINST
进行搜索:
function search_it() {
if (isset($_GET['s'])) {
global $wpdb;
$address_table = $wpdb->prefix . 'my_products';
$search = $_GET['s'];
$search = trim($search);
$where = $wpdb->prepare('WHERE MATCH(name,price,id,market_price,image_url) AGAINST (%s IN BOOLEAN MODE)', $search);
$results = $wpdb->get_results( "SELECT * FROM {$address_table} {$where} LIMIT 0,30" );
return $results;
}
}
操作步骤:
- 使用
ALTER TABLE
或者CREATE FULLTEXT INDEX
语句给对应表和字段添加FULLTEXT
索引,这里对字段的类型有要求,例如TEXT
,VARCHAR
类型字段 search_it()
函数中,where
子句使用了MATCH(name,price,id,market_price,image_url) AGAINST (%s IN BOOLEAN MODE)
,BOOLEAN MODE
可以支持更灵活的关键词搜索逻辑- 直接运行查询,不需要像前面方法那样分割关键词
FULLTEXT
索引能够快速处理大规模文本搜索,它还提供了高级的搜索操作,例如:短语匹配、排除词汇等。这种方案效率较高,更适用于文本量大的场景。
总结
对于关键词搜索需求,使用 AND
连接 LIKE
条件能满足基本需求。当数据量变大,或者对搜索性能要求高的时候,使用 FULLTEXT
索引会更加高效,通过 MATCH ... AGAINST
可以灵活设置搜索逻辑。需要注意,修改表结构务必提前备份数据,且建立索引的过程比较消耗资源,避免影响现有业务。 选择适合自己业务场景的方法是解决这类问题的关键。