本文目录导读:

为PHP项目实现拼音搜索(拼音分词索引),通常有两种主流方案:数据库内建函数/插件 和 外部分词引擎 + 索引。
考虑到性能、易用性和对中文拼音的支持度,最推荐且成熟的方案是 MySQL + 拼音分词插件 或 Elasticsearch + 拼音分词器。
以下是详细的对接步骤,以MySQL 8.0 + 自定义函数和Elasticsearch为例:
基于 MySQL 的拼音索引(适合中小型项目)
核心思路
在数据库表中增加一个 pinyin_full(全拼)和 pinyin_short(首字母)字段,插入/更新数据时,通过 PHP 或 MySQL 函数生成拼音存入,查询时,同时对原始名字和拼音字段进行 LIKE 或 MATCH...AGAINST 匹配。
准备拼音数据字典(PHP 端生成)
在 PHP 中,你需要一个汉字转拼音的库,推荐:Overtrue/Pinyin (最流行)
composer require overtrue/pinyin
数据库表设计
CREATE TABLE `product` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL, -- 原始中文名
`pinyin_initial` VARCHAR(100) DEFAULT '', -- 拼音首字母 (如: zgr)
`pinyin_full` TEXT, -- 全拼,空格分隔 (如: zhong guo ren)
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FULLTEXT INDEX `idx_pinyin_full` (`pinyin_full`), -- 用于全文检索
INDEX `idx_pinyin_initial` (`pinyin_initial`) -- 用于 LIKE 查询
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
数据操作逻辑(PHP代码)
插入/更新时:
<?php
use Overtrue\Pinyin\Pinyin;
$pinyin = new Pinyin();
// 假设 $name = "中国人";
$fullPinyin = $pinyin->sentence($name, ' '); // 输出: 'zhong guo ren'
$initialPinyin = $pinyin->abbr($name, ''); // 输出: 'zgr'
// 执行 SQL
$db->query("UPDATE product SET name='$name', pinyin_initial='$initialPinyin', pinyin_full='$fullPinyin' WHERE id=1");
?>
查询时(支持拼音首字母和全拼模糊搜索):
<?php
$keyword = $_GET['q'];
$keyword = $db->real_escape_string($keyword);
$keyword = strtolower($keyword); // 统一小写
// 核心查询逻辑:匹配原文 OR 拼音首字母 OR 拼音全拼
$sql = "SELECT * FROM product WHERE
name LIKE '%$keyword%'
OR pinyin_initial LIKE '%$keyword%'
OR MATCH(pinyin_full) AGAINST('$keyword*' IN BOOLEAN MODE)"; // 支持通配符
// 或者使用 LIKE: OR pinyin_full LIKE '%$keyword%'
?>
性能优化
- 全拼搜索:使用
FULLTEXT索引 +BOOLEAN MODE比LIKE '%keyword%'快得多。 - 首字母搜索:
pinyin_initial字段使用LIKE 'keyword%'(前缀匹配) 比%keyword%快。
基于 Elasticsearch(推荐,适合中大型及复杂搜索)
这是目前企业级项目最标准的做法,支持多音字容错、简繁搜索、模糊匹配。
服务端 & 插件安装
- 安装 Elasticsearch (7.x 或 8.x)
- 安装 IK 分词器 & 拼音分词器:
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v7.x.x/analysis-pinyin-7.x.x.zip
定义索引 Mapping(核心)
需要创建一个自定义的 Analysis(分析器),将中文转成拼音并索引。
PUT /product_index
{
"settings": {
"analysis": {
"analyzer": {
"pinyin_analyzer": {
"tokenizer": "ik_smart",
"filter": ["pinyin_filter"]
}
},
"filter": {
"pinyin_filter": {
"type": "pinyin",
"keep_full_pinyin": true,
"keep_joined_full_pinyin": true,
"keep_original": true,
"keep_first_letter": true,
"keep_none_chinese": true,
"limit_first_letter_length": 16,
"lowercase": true
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "pinyin_analyzer",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
keep_original: 保留原始中文。keep_first_letter: 保留首字母 (如 "zgr")。keep_joined_full_pinyin: 保留全拼连写 (如 "zhongguoren")。
索引文档
// 使用 Elasticsearch PHP Client (elasticsearch/elasticsearch)
$client->index([
'index' => 'product_index',
'id' => 1,
'body' => [
'name' => '中国人'
]
]);
ES会自动分词并索引拼音。
搜索查询(PHP)
$params = [
'index' => 'product_index',
'body' => [
'query' => [
'multi_match' => [
'query' => 'zgr', // 用户输入拼音首字母
'fields' => ['name'], // 它会自动匹配拼音字段
'type' => 'best_fields'
]
]
]
];
$response = $client->search($params);
优势:用户输入 zgr、zhongguoren、zhong guo ren、中国人 都能准确匹配到结果。
| 特性 | MySQL + 拼音字段 | Elasticsearch |
|---|---|---|
| 数据量 | < 50万条 | 50万+ 或需要复杂聚合 |
| 多音字处理 | 差 (需要手动维护字典) | 好 (内置支持,如“重庆”读 chongqing) |
| 搜索速度 | 中等 (FULLTEXT 索引) | 极快 (倒排索引) |
| 维护成本 | 低 (一个 Composer 包) | 高 (需要维护 ES 集群) |
| 模糊匹配 | 依赖 MySQL 全文搜索 | 支持拼音模糊、同音、错误纠正 |
总结建议
- 初创项目 / 个人博客 / 后台管理系统:使用 方案一 (MySQL + Overtrue/Pinyin),实现简单,只需额外维护两个字段。
- 电商 / 搜索应用 / 高并发 / 需要模糊/多音字支持:使用 方案二 (Elasticsearch),虽然部署复杂,但用户体验和扩展性远超 MySQL。
核心关键点:无论哪种方案,在写入数据时生成拼音并索引 都是最可靠的,不要在每次查询时动态转换拼音(性能极差)。