本文目录导读:

是的,PHP 支持同义词搜索,但PHP 本身并不内置同义词搜索引擎,它需要借助外部技术或算法来实现,以下是 PHP 实现同义词搜索的几种常见方案:
使用数据库内置功能
MySQL / MariaDB
MySQL 本身不直接支持同义词,但可以通过以下方式实现:
// 方案1:使用 LIKE 查询匹配多个同义词
$synonyms = ['手机', '移动电话', '手提电话'];
$where = [];
foreach ($synonyms as $word) {
$where[] = "title LIKE '%" . mysqli_real_escape_string($conn, $word) . "%'";
}
$sql = "SELECT * FROM products WHERE " . implode(' OR ', $where);
PostgreSQL
PostgreSQL 有 tsquery 和同义词词典支持:
-- 创建同义词词典
CREATE TEXT SEARCH DICTIONARY my_synonym (
TEMPLATE = synonym,
SYNONYMS = my_synonyms
);
CREATE TEXT SEARCH CONFIGURATION my_config (COPY = english);
ALTER TEXT SEARCH CONFIGURATION my_config
ALTER MAPPING FOR asciiword WITH my_synonym;
-- 在 PHP 中使用
$query = "SELECT * FROM documents WHERE to_tsvector('my_config', content) @@ to_tsquery('my_config', '手机')";
使用 Elasticsearch / OpenSearch
这是最强大的方案,支持完整的同义词搜索:
// 安装 elasticsearch-php 客户端
composer require elasticsearch/elasticsearch
$client = Elasticsearch\ClientBuilder::create()->build();
// 创建索引时配置同义词分析器
$params = [
'index' => 'products',
'body' => [
'settings' => [
'analysis' => [
'filter' => [
'my_synonym_filter' => [
'type' => 'synonym',
'synonyms' => [
'手机, 移动电话, 手提电话, mobile',
'电脑, 计算机, PC',
]
]
],
'analyzer' => [
'my_analyzer' => [
'tokenizer' => 'standard',
'filter' => ['lowercase', 'my_synonym_filter']
]
]
]
]
]
];
// 搜索时自动匹配同义词
$params = [
'index' => 'products',
'body' => [
'query' => [
'match' => [
'title' => '手机'
]
]
]
];
使用 PHP 数组维护同义词库
简单但有效的方案,适合中小型项目:
class SynonymSearch {
private $synonymMap = [
'手机' => ['手机', '移动电话', '手提电话', 'cellphone', 'mobile'],
'电脑' => ['电脑', '计算机', 'PC', 'computer'],
'汽车' => ['汽车', '轿车', '车辆', 'car'],
];
public function search($keyword, $data) {
// 获取同义词
$synonyms = $this->getSynonyms($keyword);
$results = [];
foreach ($data as $item) {
foreach ($synonyms as $synonym) {
if (strpos($item['title'], $synonym) !== false) {
$results[] = $item;
break;
}
}
}
return $results;
}
private function getSynonyms($keyword) {
if (isset($this->synonymMap[$keyword])) {
return $this->synonymMap[$keyword];
}
return [$keyword];
}
}
使用第三方 PHP 库
开源方案:
- sphinxsearch/sphinxapi - 基于 Sphinx 搜索引擎
- solarium/solarium - 基于 Apache Solr
- teamtnt/tntsearch - 轻量级 PHP 全文搜索引擎
TntSearch 示例:
use TeamTNT\TNTSearch\TNTSearch;
$tnt = new TNTSearch;
$tnt->loadConfig([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'test',
'username' => 'root',
'password' => '',
'storage' => '/tmp/',
]);
$tnt->selectIndex("products.index");
$res = $tnt->search("手机", 12);
使用 Redis 缓存同义词
// 存储同义词映射
$redis->hSet('synonyms', '手机', json_encode(['手机', '移动电话', '手提电话']));
// 搜索时读取
$synonyms = json_decode($redis->hGet('synonyms', $keyword), true);
$searchTerms = is_array($synonyms) ? $synonyms : [$keyword];
综合实现方案(推荐)
对于大多数 PHP 项目,推荐组合使用:
class SmartSearch {
private $pdo;
private $synonymTable = 'synonyms';
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function search($keyword, $limit = 10) {
// 1. 获取同义词
$synonyms = $this->getSynonymsFromDB($keyword);
// 2. 构建查询
$sql = "SELECT * FROM products WHERE ";
$conditions = [];
foreach ($synonyms as $i => $word) {
$conditions[] = "title LIKE :word" . $i;
$params[":word" . $i] = "%" . $word . "%";
}
$sql .= implode(' OR ', $conditions);
$sql .= " LIMIT " . intval($limit);
// 3. 执行查询
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
// 4. 按相关度排序
return $this->rankResults($stmt->fetchAll(), $keyword);
}
private function getSynonymsFromDB($keyword) {
$stmt = $this->pdo->prepare("SELECT synonym FROM synonyms WHERE base_word = ?");
$stmt->execute([$keyword]);
$synonyms = $stmt->fetchAll(PDO::FETCH_COLUMN);
array_unshift($synonyms, $keyword); // 在开头添加原词
return array_unique($synonyms);
}
}
选择建议
| 方案 | 适用场景 | 复杂度 | 性能 |
|---|---|---|---|
| 数据库 LIKE + PHP 数组 | 小规模数据 | 低 | 一般 |
| PHP 词典 + 缓存 | 中等规模 | 中 | 较好 |
| Elasticsearch | 大规模、需要分词 | 高 | 优秀 |
| TntSearch | 中小规模独立搜索 | 中 | 良好 |
| PostgreSQL 字典 | 使用 PostgreSQL 的项目 | 中 | 良好 |
注意事项
- 同义词匹配模式:需要支持多语言、模糊匹配、拼音转换等
- 性能优化:使用索引、缓存同义词映射
- 扩展性:设计可动态添加同义词的方案
- 相关性排序:精确匹配应优先于同义词匹配
你具体是什么场景?可以给我更多细节,我可以给你更有针对性的实现建议。