本文目录导读:

在PHP项目中实现同义词扩展,通常有以下几种常见方法,具体选择取决于你的项目需求和数据规模:
数据库存储方案(推荐中小型项目)
创建同义词表
CREATE TABLE synonyms (
id INT PRIMARY KEY AUTO_INCREMENT,
word VARCHAR(255) NOT NULL,
synonym VARCHAR(255) NOT NULL,
group_id INT NOT NULL,
UNIQUE KEY unique_pair (word, synonym)
);
-- 创建索引
CREATE INDEX idx_word ON synonyms(word);
CREATE INDEX idx_group ON synonyms(group_id);
插入示例数据
INSERT INTO synonyms (word, synonym, group_id) VALUES
('快乐', '高兴', 1),
('快乐', '愉快', 1),
('高兴', '快乐', 1),
('高兴', '愉快', 1),
('快速', '迅速', 2),
('快速', '敏捷', 2);
PHP查询示例
class SynonymManager {
private $db;
public function __construct(PDO $db) {
$this->db = $db;
}
// 获取所有同义词
public function getSynonyms(string $word): array {
$stmt = $this->db->prepare("
SELECT synonym FROM synonyms
WHERE word = ?
");
$stmt->execute([$word]);
return $stmt->fetchAll(PDO::FETCH_COLUMN);
}
// 扩展搜索关键词
public function expandQuery(string $query): array {
$words = explode(' ', $query);
$expandedWords = [$words];
foreach ($words as $word) {
$synonyms = $this->getSynonyms($word);
if (!empty($synonyms)) {
$expandedWords[] = $synonyms;
}
}
return array_unique(array_merge(...$expandedWords));
}
}
内存缓存方案(推荐高性能场景)
使用Redis存储
class RedisSynonymManager {
private $redis;
public function __construct(Redis $redis) {
$this->redis = $redis;
}
// 加载同义词到Redis
public function loadSynonyms(array $synonymGroups): void {
foreach ($synonymGroups as $groupId => $words) {
$key = "synonyms:group:{$groupId}";
$this->redis->sAddArray($key, $words);
// 建立反向索引
foreach ($words as $word) {
$this->redis->sAdd("synonyms:word:{$word}", ...$words);
$this->redis->sRem("synonyms:word:{$word}", $word); // 移除自身
}
}
}
// 获取同义词
public function getSynonyms(string $word): array {
return $this->redis->sMembers("synonyms:word:{$word}") ?? [];
}
}
配置文件方案(简单小型项目)
synonyms.json
{
"group1": ["快乐", "高兴", "愉快", "欢乐"],
"group2": ["快速", "迅速", "敏捷", "迅猛"],
"group3": ["美丽", "漂亮", "好看", "迷人"]
}
PHP实现
class ConfigSynonymManager {
private array $synonyms;
private array $reverseIndex = [];
public function __construct(string $configFile) {
$this->synonyms = json_decode(file_get_contents($configFile), true);
$this->buildReverseIndex();
}
private function buildReverseIndex(): void {
foreach ($this->synonyms as $group => $words) {
foreach ($words as $word) {
$this->reverseIndex[$word] = array_diff($words, [$word]);
}
}
}
public function getSynonyms(string $word): array {
return $this->reverseIndex[$word] ?? [];
}
}
搜索引擎集成方案(推荐全文搜索场景)
使用Elasticsearch
class ElasticsearchSynonymManager {
private $client;
public function __construct() {
$this->client = Elasticsearch\ClientBuilder::create()->build();
}
// 创建带同义词的分析器
public function setupSynonymAnalyzer(): void {
$params = [
'index' => 'my_index',
'body' => [
'settings' => [
'analysis' => [
'filter' => [
'my_synonym_filter' => [
'type' => 'synonym',
'synonyms' => [
'快乐, 高兴, 愉快',
'快速, 迅速, 敏捷'
]
]
],
'analyzer' => [
'my_synonym_analyzer' => [
'tokenizer' => 'standard',
'filter' => ['lowercase', 'my_synonym_filter']
]
]
]
]
]
];
$this->client->indices()->create($params);
}
}
完整示例:搜索功能实现
<?php
class SearchEngine {
private SynonymManager $synonymManager;
private DatabaseManager $db;
public function search(string $query): array {
// 1. 扩展关键词
$expandedTerms = $this->expandTerms($query);
// 2. 构建搜索SQL
$sql = $this->buildSearchQuery($expandedTerms);
// 3. 执行搜索
return $this->db->query($sql)->fetchAll();
}
private function expandTerms(string $query): array {
$terms = explode(' ', $query);
$allTerms = [];
foreach ($terms as $term) {
$allTerms[] = $term;
$synonyms = $this->synonymManager->getSynonyms($term);
$allTerms = array_merge($allTerms, $synonyms);
}
return array_unique($allTerms);
}
private function buildSearchQuery(array $terms): string {
$likeClauses = [];
foreach ($terms as $term) {
$likeClauses[] = "content LIKE '%" . $this->db->escape($term) . "%'";
}
return "SELECT * FROM articles WHERE " . implode(' OR ', $likeClauses);
}
}
性能优化建议
索引优化
// 使用Trie树优化大词汇表
class TrieSynonymManager {
private TrieNode $root;
public function buildSynonymTrie(array $synonymData): void {
foreach ($synonymData as $word => $synonyms) {
$current = $this->root;
foreach (str_split($word) as $char) {
if (!isset($current->children[$char])) {
$current->children[$char] = new TrieNode();
}
$current = $current->children[$char];
}
$current->synonyms = $synonyms;
}
}
public function getSynonyms(string $word): array {
$current = $this->root;
foreach (str_split($word) as $char) {
if (!isset($current->children[$char])) {
return [];
}
$current = $current->children[$char];
}
return $current->synonyms ?? [];
}
}
缓存策略
class CachedSynonymManager {
private $cache;
private $ttl = 3600; // 1小时缓存
public function getSynonyms(string $word): array {
$cacheKey = "synonym:{$word}";
// 尝试从缓存获取
if ($cached = $this->cache->get($cacheKey)) {
return $cached;
}
// 从数据库获取
$synonyms = $this->fetchFromDatabase($word);
// 存入缓存
$this->cache->set($cacheKey, $synonyms, $this->ttl);
return $synonyms;
}
}
选择建议
| 场景 | 推荐方案 |
|---|---|
| 小型项目、词汇量小 | 配置文件方案 |
| 中大型项目、需要持久化 | 数据库方案 |
| 高性能、大并发 | Redis缓存 |
| 全文搜索 | Elasticsearch |
| 中文分词+同义词 | 集成中文分词插件 |
选择时需考虑:数据量大小、性能要求、更新频率、部署复杂度等因素。