PHP 搭建个人博客原创搜索:结合 MySQL 全文索引与权重排序算法

一、技术方案核心
  1. MySQL 全文索引

    • 对博客文章的标题(title)、内容(content)等字段建立全文索引
    • 使用 MATCH() AGAINST() 实现关键词搜索
    • 支持中文分词(需 MySQL 5.7+ 的 ngram 分词器)
  2. 权重排序算法
    综合以下因素计算权重得分:
    $$ \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>";
}


三、算法优化点
  1. 动态权重调整
    根据用户行为动态调整权重系数:

    // 用户偏好新鲜内容时
    $weights = [0.5, 0.4, 0.1]; 
    
    // 用户偏好热门内容时
    $weights = [0.5, 0.2, 0.3];
    

  2. 搜索结果高亮
    使用 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;
    }
    

  3. 分词优化
    中文分词增强方案:

    // 使用结巴分词预处理关键词
    require 'vendor/autoload.php';
    use Fukuball\Jieba\Jieba;
    
    Jieba::init();
    $segmented = Jieba::cutForSearch($keyword);
    $optimizedKeyword = implode(' ', $segmented);
    


四、性能优化建议
  1. 缓存机制
    对热门搜索词结果缓存 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));
    }
    

  2. 异步索引更新
    文章发布后异步更新索引:

    # 使用消息队列
    php artisan queue:work --queue=search_index
    

  3. 负载均衡

    graph LR
    A[用户请求] --> B(Nginx负载均衡)
    B --> C[PHP服务器1]
    B --> D[PHP服务器2]
    B --> E[PHP服务器3]
    C & D & E --> F[(MySQL集群)]
    


五、扩展方案

当数据量超过百万级时:

  1. 采用 Elasticsearch 替代 MySQL 全文搜索
  2. 实现 BERT 语义相似度 计算
  3. 增加 个性化推荐 权重因子: $$ \text{score} += w_4 \times \text{用户兴趣匹配度} $$

提示:初始阶段使用 MySQL 方案可快速上线,后期根据业务增长逐步升级架构。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐