PHP 搭建个人博客原创搜索:结合 MySQL 全文索引与权重排序算法
·
PHP 搭建个人博客原创搜索:结合 MySQL 全文索引与权重排序算法
一、技术方案核心
-
MySQL 全文索引
- 对博客文章的标题(
title)、内容(content)等字段建立全文索引 - 使用
MATCH() AGAINST()实现关键词搜索 - 支持中文分词(需 MySQL 5.7+ 的 ngram 分词器)
- 对博客文章的标题(
-
权重排序算法
综合以下因素计算权重得分:
$$ \text{score} = w_1 \times \text{相关性} + w_2 \times \text{时效性} + w_3 \times \text{用户交互} $$- $w_1$:全文检索相关性权重(默认 0.6)
- $w_2$:发布时间权重(默认 0.3)
- $w_3$:用户交互权重(默认 0.1)
二、实现步骤
1. 数据库设计
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
views INT DEFAULT 0 -- 阅读量
);
-- 创建全文索引(支持中文)
ALTER TABLE articles ADD FULLTEXT INDEX ft_search (title, content)
WITH PARSER ngram;
2. 权重排序算法实现
function searchArticles($keyword, $weights = [0.6, 0.3, 0.1]) {
// 归一化权重
$total = array_sum($weights);
$w1 = $weights[0] / $total;
$w2 = $weights[1] / $total;
$w3 = $weights[2] / $total;
$sql = "SELECT id, title,
MATCH(title, content) AGAINST(:keyword) AS relevance,
(1 / (1 + DATEDIFF(NOW(), created_at))) AS freshness, -- 时效性因子
LOG10(views + 1) AS engagement, -- 用户交互因子
-- 综合权重得分
($w1 * MATCH(title, content) AGAINST(:keyword) +
$w2 * (1 / (1 + DATEDIFF(NOW(), created_at))) +
$w3 * LOG10(views + 1)) AS score
FROM articles
WHERE MATCH(title, content) AGAINST(:keyword IN BOOLEAN MODE)
ORDER BY score DESC
LIMIT 20";
// 执行查询(使用PDO预处理防SQL注入)
$stmt = $pdo->prepare($sql);
$stmt->execute([':keyword' => $keyword]);
return $stmt->fetchAll();
}
3. 搜索接口示例
// 获取搜索关键词
$keyword = $_GET['q'] ?? '';
// 执行权重搜索
$results = searchArticles($keyword);
// 展示结果
foreach ($results as $article) {
echo "<article>
<h3>{$article['title']}</h3>
<p>相关性: ".round($article['relevance'], 2)."</p>
<p>综合得分: ".round($article['score'], 2)."</p>
</article>";
}
三、算法优化点
-
动态权重调整
根据用户行为动态调整权重系数:// 用户偏好新鲜内容时 $weights = [0.5, 0.4, 0.1]; // 用户偏好热门内容时 $weights = [0.5, 0.2, 0.3]; -
搜索结果高亮
使用 PHP 的preg_replace实现关键词高亮:function highlightKeywords($text, $keyword) { $words = explode(' ', $keyword); foreach ($words as $word) { $text = preg_replace("/($word)/i", '<mark>$1</mark>', $text); } return $text; } -
分词优化
中文分词增强方案:// 使用结巴分词预处理关键词 require 'vendor/autoload.php'; use Fukuball\Jieba\Jieba; Jieba::init(); $segmented = Jieba::cutForSearch($keyword); $optimizedKeyword = implode(' ', $segmented);
四、性能优化建议
-
缓存机制
对热门搜索词结果缓存 1 小时:$cacheKey = "search:" . md5($keyword); if ($cached = $redis->get($cacheKey)) { return json_decode($cached, true); } else { $results = searchArticles($keyword); $redis->setex($cacheKey, 3600, json_encode($results)); } -
异步索引更新
文章发布后异步更新索引:# 使用消息队列 php artisan queue:work --queue=search_index -
负载均衡
graph LR A[用户请求] --> B(Nginx负载均衡) B --> C[PHP服务器1] B --> D[PHP服务器2] B --> E[PHP服务器3] C & D & E --> F[(MySQL集群)]
五、扩展方案
当数据量超过百万级时:
- 采用 Elasticsearch 替代 MySQL 全文搜索
- 实现 BERT 语义相似度 计算
- 增加 个性化推荐 权重因子: $$ \text{score} += w_4 \times \text{用户兴趣匹配度} $$
提示:初始阶段使用 MySQL 方案可快速上线,后期根据业务增长逐步升级架构。
更多推荐
所有评论(0)