遭遇了 “黑天鹅” 事件

近期真是遭遇了 “黑天鹅” 事件,公司因卷入非法问题,面临一系列棘手处理,无奈之下只得遣散全体员工,我也因此瞬间失业。原本按部就班的工作节奏戛然而止,每天醒来,看着毫无安排的一天,心里满是茫然与失落。与其在这种不确定中焦虑徘徊,倒不如主动出击,给自己找点事儿做。我打算投身到文档撰写中,既能有效填补空闲时间,让生活重回正轨,也能借此梳理过往积累的知识与经验,为未来求职筑牢根基,让这段意外失业的日子,不至于虚度 。

什么是Sphinx? 有什么优缺点呢?

  • phinx 是开源全文搜索引擎。
  • 优点是高性能、功能丰富、可扩展性好、多语言支持、开源成本低;
  • 缺点是配置复杂、对内存要求高、实时性有限、缺乏图形化管理界面。

安装和配置

  • sphinx官网下载页面
  • 服务器:CentOS7,glibc版本2.17
  • 安装

    # 创建存放sphinx软件目录
    mkdir -p /usr/local/sphinx/
    
    # 进入/usr/local/sphinx/文件夹
    cd /usr/local/sphinx/
    
    # 下载对应的glibc版本的sphinx软件包
    wget https://sphinxsearch.com/files/sphinx-3.7.1-da9f8a4-linux-amd64-glibc2.17.tar.gz
    
    # 解压  
    tar -zxvf sphinx-3.7.1-da9f8a4-linux-amd64-glibc2.17.tar.gz
  • 配置

    # 进入到配置目录
    cd /usr/local/sphinx/sphinx-3.7.1/etc/
    # 创建文件,把配置粘贴进去
    vim sphinx.conf
    ======================================================
    # 通用配置部分,定义一些全局的设置
    common
    {
      # 数据目录,用于存放索引文件和其他相关数据
      datadir = ./sphinxdata
    }
    
    # 数据源配置,这里以 MySQL 数据库为例
    source names_1_source
    {
      # 数据源类型为 MySQL
      type = mysql
      # 数据库主机地址,使用 127.0.0.1 以确保端口配置生效
      sql_host = 127.0.0.1
      # 数据库用户名
      sql_user = active
      # 数据库密码
      sql_pass = PcjcrN53sR8bdZyx
      # 要连接的数据库名
      sql_db = active
      # 数据库端口号,默认是 3306
      sql_port = 3306
      # SQL 查询语句,用于从数据库中获取要索引的数据
      sql_query = SELECT id, surname, name, first, second, gender, type, score, details FROM names_1
      # 在执行查询前设置字符集为 UTF-8,确保中文等字符能正确处理
      sql_query_pre = SET NAMES utf8mb4
    }
    
    # 索引配置
    index names_1_index
    {
      # 索引类型为普通索引
      type = plain
      # 关联的数据源
      source = names_1_source
      # 要进行全文搜索的字段
      field =  surname, details
    
      # 定义属性,用于排序、过滤等操作
      attr_uint = gender, type  # 无符号整数类型的属性
      attr_float = score  # 浮点数类型的属性
      attr_string = name, first, second  # 字符串类型的属性
    
      # 字符集表,涵盖了数字、英文字母(大小写统一)、中文、日文、韩文等字符范围
      # charset_table =
      # 最小词长度,设置为 1 表示单字符也会被索引,适用于中文和单字母搜索
      min_word_len = 1
      # 词形处理方式,这里设置为不进行词形处理
      morphology = none
      # N - gram 长度,设置为 1 表示按单字符进行 N - gram 索引,有助于中文搜索
      ngram_len = 1
      # 指定用于 N - gram 索引的字符范围,这里包含了中文、日文、韩文等字符
      ngram_chars = U+4E00..U+9FBB, U+3400..U+4DB5, U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27, U+FA28, U+FA29, U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043, U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057, U+3059, U+305B, U+305D, U+305F, U+3061, U+3063, U+3066, U+3068, U+306A..U+306F, U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, U+3085, U+3087, U+3089..U+308E, U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7, U+30A9, U+30AD, U+30AF, U+30B3, U+30B5, U+30BB, U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB, U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3, U+30E5, U+30E7, U+30EE, U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5, U+31F6, U+31F7, U+31F8, U+31F9, U+31FA, U+31FB, U+31FC, U+31FD, U+31FE, U+31FF, U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C, U+A492..U+A4C6
    }
    
    # 搜索服务配置
    searchd
    {
      # 监听的地址和端口,客户端通过此端口连接搜索服务
      listen = 9312
      # 搜索服务的日志文件路径,记录服务的运行信息
      log = no
      # 查询日志文件路径,记录用户的查询请求,方便后续分析和优化
      query_log = no
      # 进程 ID 文件路径,用于管理搜索服务进程
      # pid_file = ""
      # 启用无缝索引切换,在重建索引时不影响搜索服务的正常运行
      seamless_rotate = 1
      # 是否预先打开所有索引文件,根据服务器内存和性能情况调整
      preopen_indexes = 0
      # 自动删除旧的索引文件,节省磁盘空间
      unlink_old = 1
      # 客户端连接超时时间(秒)
      client_timeout = 30
    }
    ======================================================

    测试 数据库active下的表names_1大概是这样的

    mysql.png

启动sphinx和停止

# 可读权限
sudo chmod -R a+r /usr/local/sphinx/sphinx-3.7.1
# 启动
./searchd -c /usr/local/sphinx/sphinx-3.7.1/etc/sphinx.conf

# 停止
./searchd --stop -c /usr/local/sphinx/sphinx-3.7.1/etc/sphinx.conf

创建和更新索引

sudo chmod -R a+r /usr/local/sphinx/sphinx-3.7.1
sudo chmod u+w /usr/local/sphinx/sphinx-3.7.1/bin/indexer
cd /usr/local/sphinx/sphinx-3.7.1/bin/
./indexer -c /usr/local/sphinx/sphinx-3.7.1/etc/sphinx.conf --all --rotate

# ./indexer是 Sphinx 索引器程序。
# -c /usr/local/sphinx/sphinx-3.7.1/etc/sphinx.conf指定配置文件路径。
# --all对配置里所有索引操作。
# --rotate在searchd运行时无缝更新索引,不中断搜索服务。

查看端口和sphinx服务

# 查看端口
ps -ef | grep searchd|grep -v "grep"
netstat -an | grep 9312

# 对外防火墙放开端口
# 查询是否开启
sudo firewall-cmd --query-port=9312/tcp
# 开启
sudo firewall-cmd --add-port=9312/tcp --permanent
# 重启生效
sudo firewall-cmd --reload

php 使用

  • 首先复制一份/usr/local/sphinx/sphinx-3.7.1/api/sphinxapi.php 文件到你的项目目录。

    <?php
    declare(strict_types=1);
    require __DIR__.'./vendor/autoload.php';
    require __DIR__."/sphinxapi.php";
    
    use Fukuball\Jieba\Jieba;
    //use Fukuball\Jieba\Posseg;
    
    ini_set('memory_limit','512M');
    //分词
    Jieba::init();
    //Posseg::init();
    $searchQuery = 'Firaxis';
    if (hasChinese($searchQuery)) {
      $cutWord = Jieba::cut($searchQuery);
      $searchQuery = implode('|', $cutWord);
    }
    echo '查找关键词:'.$searchQuery.'</br>';
    // 创建 Sphinx 客户端对象
    $cl = new SphinxClient();
    // 设置 Sphinx 服务器的主机和端口
    $cl->SetServer('127.0.0.1',9312);
    $t = $_GET['type'] ?? 1;
    switch ($t)
    {
      case 1:
          // 设置搜索的偏移量和返回结果数量
          $cl->SetLimits(0, 10);
          // 设置排序模式为按相关性排序
          $cl->SetSortMode(SPH_SORT_RELEVANCE);
          $index = 'names_1_index';
    //        $cl->SetFilterString('details','Firaxis');
          $result = $cl->query($searchQuery, $index);
          if ($result === false) {
              echo '查询错误: '. $cl->GetLastError();
          } else {
              // 处理查询结果
              if ($result['total'] > 0) {
                  foreach ($result['matches'] as $id => $match) {
                      echo '文档ID: '. $id. ',姓名:'.$match['attrs']['name'].',score:'.$match['attrs']['score']. ',相关性得分: '. $match['weight']. '<br>';
                      // 可以根据索引中的字段获取更多信息
                  }
              } else {
                  echo '没有找到匹配的结果';
              }
          }
          break;
      case 2:
          //TODO  更新数据库
          
          $index = 'names_1_index';
          $attrs = ['score'];
          $values = [
              4048551 => [100], // 文档 ID 为 1 的文档,将 'price' 属性更新为 100
              4048552 => [200]  // 文档 ID 为 2 的文档,将 'price' 属性更新为 200
          ];
          $updated = $cl->UpdateAttributes($index, $attrs, $values);
          if ($updated >= 0) {
              echo "成功更新 $updated 条文档的属性。";
          } else {
              echo "更新属性时出错: ". $cl->GetLastError();
          }
          break;
    }
    
    function hasChinese($str) {
      for ($i = 0; $i < mb_strlen($str); $i++) {
          $char = mb_substr($str, $i, 1);
          $ord = mb_convert_encoding($char, 'UCS-2BE', 'UTF-8');
          $code = hexdec(bin2hex($ord));
          if ($code >= 0x4E00 && $code <= 0x9FA5) {
              return true;
          }
      }
      return false;
    }
    

查询结果

结果.png

Last modification:February 28, 2025
如果觉得我的文章对你有用,请随意赞赏